From 5d0b8e9053ec21d3162517426327829957975f5d Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 24 Feb 2021 16:51:33 -0300 Subject: [PATCH 01/58] updated logger method names --- jest.config.js | 2 +- package-lock.json | 2 +- package.json | 5 +- src/evaluator/combiners/and.ts | 2 +- src/evaluator/combiners/ifelseif.ts | 6 +-- src/evaluator/condition/engineUtils.ts | 2 +- src/evaluator/matchers/all.ts | 2 +- src/evaluator/matchers/between.ts | 2 +- src/evaluator/matchers/boolean.ts | 2 +- src/evaluator/matchers/cont_all.ts | 2 +- src/evaluator/matchers/cont_any.ts | 2 +- src/evaluator/matchers/cont_str.ts | 2 +- src/evaluator/matchers/dependency.ts | 4 +- src/evaluator/matchers/eq.ts | 2 +- src/evaluator/matchers/eq_set.ts | 2 +- src/evaluator/matchers/ew.ts | 2 +- src/evaluator/matchers/gte.ts | 2 +- src/evaluator/matchers/lte.ts | 2 +- src/evaluator/matchers/part_of.ts | 2 +- src/evaluator/matchers/segment.ts | 4 +- src/evaluator/matchers/string.ts | 4 +- src/evaluator/matchers/sw.ts | 2 +- src/evaluator/matchers/whitelist.ts | 2 +- src/evaluator/value/index.ts | 6 +-- src/evaluator/value/sanitize.ts | 2 +- src/integrations/ga/GaToSplit.ts | 14 +++--- src/integrations/ga/SplitToGa.ts | 10 ++-- .../ga/__tests__/SplitToGa.spec.ts | 4 +- src/listeners/browser.ts | 4 +- src/listeners/node.ts | 8 +-- src/logger/__tests__/index.spec.ts | 20 ++++---- src/logger/__tests__/sdkLogger.mock.ts | 16 +++--- src/logger/index.ts | 8 +-- src/logger/sdkLogger.ts | 2 +- .../__tests__/sdkReadinessManager.spec.ts | 50 +++++++++---------- src/readiness/sdkReadinessManager.ts | 8 +-- src/sdkClient/client.ts | 4 +- src/sdkClient/sdkClientMethod.ts | 2 +- src/sdkClient/sdkClientMethodCS.ts | 6 +-- src/sdkClient/sdkClientMethodCSWithTT.ts | 6 +-- src/sdkFactory/index.ts | 6 +-- src/services/splitHttpClient.ts | 4 +- .../inLocalStorage/MySegmentsCacheInLocal.ts | 6 +-- .../inLocalStorage/SplitsCacheInLocal.ts | 18 +++---- src/storages/inLocalStorage/index.ts | 2 +- src/storages/inRedis/EventsCacheInRedis.ts | 2 +- src/storages/inRedis/RedisAdapter.ts | 18 +++---- src/storages/inRedis/SplitsCacheInRedis.ts | 10 ++-- .../inRedis/__tests__/RedisAdapter.spec.ts | 42 ++++++++-------- .../splitsParser/splitsParserFromFile.ts | 12 ++--- .../offline/syncTasks/fromObjectSyncTask.ts | 6 +-- src/sync/polling/pollingManagerCS.ts | 6 +-- src/sync/polling/pollingManagerSS.ts | 8 +-- .../polling/syncTasks/mySegmentsSyncTask.ts | 2 +- .../polling/syncTasks/segmentsSyncTask.ts | 8 +-- src/sync/polling/syncTasks/splitsSyncTask.ts | 12 ++--- src/sync/streaming/SSEHandler/index.ts | 6 +-- src/sync/streaming/pushManager.ts | 16 +++--- src/sync/streaming/pushManagerCS.ts | 16 +++--- src/sync/streaming/pushManagerSS.ts | 16 +++--- src/sync/submitters/eventsSyncTask.ts | 2 +- src/sync/submitters/submitterSyncTask.ts | 8 +-- src/sync/syncManagerOnline.ts | 6 +-- src/sync/syncTask.ts | 6 +-- src/trackers/eventTracker.ts | 4 +- src/trackers/impressionsTracker.ts | 6 +-- .../inputValidation/__tests__/apiKey.spec.ts | 22 ++++---- .../__tests__/attributes.spec.ts | 14 +++--- .../inputValidation/__tests__/event.spec.ts | 14 +++--- .../__tests__/eventProperties.spec.ts | 38 +++++++------- .../__tests__/eventValue.spec.ts | 18 +++---- .../__tests__/isOperational.spec.ts | 20 ++++---- .../inputValidation/__tests__/key.spec.ts | 48 +++++++++--------- .../__tests__/preloadedData.spec.ts | 12 ++--- .../inputValidation/__tests__/split.spec.ts | 20 ++++---- .../__tests__/splitExistance.spec.ts | 14 +++--- .../inputValidation/__tests__/splits.spec.ts | 18 +++---- .../__tests__/trafficType.spec.ts | 16 +++--- .../__tests__/trafficTypeExistance.spec.ts | 32 ++++++------ src/utils/inputValidation/apiKey.ts | 10 ++-- src/utils/inputValidation/attributes.ts | 2 +- src/utils/inputValidation/event.ts | 8 +-- src/utils/inputValidation/eventProperties.ts | 8 +-- src/utils/inputValidation/eventValue.ts | 2 +- src/utils/inputValidation/isOperational.ts | 4 +- src/utils/inputValidation/key.ts | 12 ++--- src/utils/inputValidation/preloadedData.ts | 12 ++--- src/utils/inputValidation/split.ts | 8 +-- src/utils/inputValidation/splitExistance.ts | 2 +- src/utils/inputValidation/splits.ts | 2 +- src/utils/inputValidation/trafficType.ts | 8 +-- .../inputValidation/trafficTypeExistance.ts | 2 +- .../__tests__/splitFilters.spec.ts | 28 +++++------ .../settingsValidation/impressionsMode.ts | 2 +- .../settingsValidation/integrations/common.ts | 2 +- src/utils/settingsValidation/splitFilters.ts | 8 +-- .../settingsValidation/storage/storageCS.ts | 2 +- src/utils/timeTracker/index.ts | 2 +- 98 files changed, 444 insertions(+), 443 deletions(-) diff --git a/jest.config.js b/jest.config.js index ed62d821..439ab3b6 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,7 +2,7 @@ module.exports = { preset: 'ts-jest', // Test files are .js and .ts files inside of __tests__ folders and with a suffix of .test or .spec - testMatch: ['**/__tests__/**/?(*.)+(spec|test).[jt]s'], + testMatch: ['/src/**/__tests__/**/?(*.)+(spec|test).[jt]s'], // Included files for test coverage (npm run test:coverage) collectCoverageFrom: [ diff --git a/package-lock.json b/package-lock.json index 67225cc9..a4d7edff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "0.0.1-beta1", + "version": "0.0.1-beta.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0bac85bd..d0a9df2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "0.0.1-beta1", + "version": "0.0.1-beta.2", "description": "Split Javascript SDK common components", "main": "cjs/index.js", "module": "esm/index.js", @@ -24,7 +24,8 @@ "build:cjs": "rimraf cjs && tsc -m CommonJS --outDir cjs --importHelpers", "test": "jest", "test:coverage": "jest --coverage", - "publish:rc": "npm run check && npm run test && npm run build && npm publish --tag rc" + "publish:rc": "npm run check && npm run test && npm run build && npm publish --tag rc", + "publish:stable": "npm run check && npm run test && npm run build && npm publish" }, "repository": { "type": "git", diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index 761fb079..853cd639 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -9,7 +9,7 @@ function andResults(results: boolean[]): boolean { // Array.prototype.every is supported by target environments const hasMatchedAll = results.every(value => value); - log.debug(`[andCombiner] evaluates to ${hasMatchedAll}`); + log.d(`[andCombiner] evaluates to ${hasMatchedAll}`); return hasMatchedAll; } diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index 961b05a9..818b5302 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -8,7 +8,7 @@ import { SplitIO } from '../../types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; function unexpectedInputHandler() { - log.error('Invalid Split provided, no valid conditions found'); + log.e('Invalid Split provided, no valid conditions found'); return { treatment: CONTROL, @@ -23,13 +23,13 @@ function computeTreatment(predicateResults: Array) { const evaluation = predicateResults[i]; if (evaluation !== undefined) { - log.debug(`Treatment found: ${evaluation.treatment}`); + log.d(`Treatment found: ${evaluation.treatment}`); return evaluation; } } - log.debug('All predicates evaluated, no treatment found.'); + log.d('All predicates evaluated, no treatment found.'); return undefined; } diff --git a/src/evaluator/condition/engineUtils.ts b/src/evaluator/condition/engineUtils.ts index b21ce367..7b5a4925 100644 --- a/src/evaluator/condition/engineUtils.ts +++ b/src/evaluator/condition/engineUtils.ts @@ -10,7 +10,7 @@ export function getTreatment(key: string, seed: number, treatments: { getTreatme const treatment = treatments.getTreatmentFor(_bucket); - log.debug(`[engine] using algo 'murmur' bucket ${_bucket} for key ${key} using seed ${seed} - treatment ${treatment}`); + log.d(`[engine] using algo 'murmur' bucket ${_bucket} for key ${key} using seed ${seed} - treatment ${treatment}`); return treatment; } diff --git a/src/evaluator/matchers/all.ts b/src/evaluator/matchers/all.ts index 0a4fd8a2..0fec9b93 100644 --- a/src/evaluator/matchers/all.ts +++ b/src/evaluator/matchers/all.ts @@ -2,7 +2,7 @@ import { logFactory } from '../../logger/sdkLogger'; const log = logFactory('splitio-engine:matcher'); function allMatcher(runtimeAttr: string): boolean { - log.debug('[allMatcher] is always true'); + log.d('[allMatcher] is always true'); return runtimeAttr != null; } diff --git a/src/evaluator/matchers/between.ts b/src/evaluator/matchers/between.ts index ba17c6c8..bedf3a7e 100644 --- a/src/evaluator/matchers/between.ts +++ b/src/evaluator/matchers/between.ts @@ -7,7 +7,7 @@ export default function betweenMatcherContext(ruleVO: IBetweenMatcherData) /*: F let isBetween = runtimeAttr >= ruleVO.start && runtimeAttr <= ruleVO.end; - log.debug(`[betweenMatcher] is ${runtimeAttr} between ${ruleVO.start} and ${ruleVO.end}? ${isBetween}`); + log.d(`[betweenMatcher] is ${runtimeAttr} between ${ruleVO.start} and ${ruleVO.end}? ${isBetween}`); return isBetween; }; diff --git a/src/evaluator/matchers/boolean.ts b/src/evaluator/matchers/boolean.ts index f9c5d4cc..3b35967f 100644 --- a/src/evaluator/matchers/boolean.ts +++ b/src/evaluator/matchers/boolean.ts @@ -5,7 +5,7 @@ export default function booleanMatcherContext(ruleAttr: boolean) /*: Function */ return function booleanMatcher(runtimeAttr: boolean): boolean { let booleanMatches = ruleAttr === runtimeAttr; - log.debug(`[booleanMatcher] ${ruleAttr} === ${runtimeAttr}`); + log.d(`[booleanMatcher] ${ruleAttr} === ${runtimeAttr}`); return booleanMatches; }; diff --git a/src/evaluator/matchers/cont_all.ts b/src/evaluator/matchers/cont_all.ts index 51e2eccb..68bfaf12 100644 --- a/src/evaluator/matchers/cont_all.ts +++ b/src/evaluator/matchers/cont_all.ts @@ -15,7 +15,7 @@ export default function containsAllMatcherContext(ruleAttr: string[]) /*: Functi } } - log.debug(`[containsAllMatcher] ${runtimeAttr} contains all elements of ${ruleAttr}? ${containsAll}`); + log.d(`[containsAllMatcher] ${runtimeAttr} contains all elements of ${ruleAttr}? ${containsAll}`); return containsAll; }; diff --git a/src/evaluator/matchers/cont_any.ts b/src/evaluator/matchers/cont_any.ts index d0e87c6f..569873fd 100644 --- a/src/evaluator/matchers/cont_any.ts +++ b/src/evaluator/matchers/cont_any.ts @@ -10,7 +10,7 @@ export default function containsAnyMatcherContext(ruleAttr: string[]) /*: Functi if (findIndex(runtimeAttr, e => e === ruleAttr[i]) >= 0) containsAny = true; } - log.debug(`[containsAnyMatcher] ${runtimeAttr} contains at least an element of ${ruleAttr}? ${containsAny}`); + log.d(`[containsAnyMatcher] ${runtimeAttr} contains at least an element of ${ruleAttr}? ${containsAny}`); return containsAny; }; diff --git a/src/evaluator/matchers/cont_str.ts b/src/evaluator/matchers/cont_str.ts index ee551238..72cf50b2 100644 --- a/src/evaluator/matchers/cont_str.ts +++ b/src/evaluator/matchers/cont_str.ts @@ -6,7 +6,7 @@ export default function containsStringMatcherContext(ruleAttr: string[]) /*: Fun return function containsStringMatcher(runtimeAttr: string): boolean { let contains = ruleAttr.some(e => isString(runtimeAttr) && runtimeAttr.indexOf(e) > -1); - log.debug(`[containsStringMatcher] ${runtimeAttr} contains ${ruleAttr}? ${contains}`); + log.d(`[containsStringMatcher] ${runtimeAttr} contains ${ruleAttr}? ${contains}`); return contains; }; diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index cdbd5486..36692a9c 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -12,7 +12,7 @@ function checkTreatment(evaluation: IEvaluation, acceptableTreatments: string[], matches = acceptableTreatments.indexOf(evaluation.treatment as string) !== -1; } - log.debug(`[dependencyMatcher] Parent split "${parentName}" evaluated to "${evaluation.treatment}" with label "${evaluation.label}". ${parentName} evaluated treatment is part of [${acceptableTreatments}] ? ${matches}.`); + log.d(`[dependencyMatcher] Parent split "${parentName}" evaluated to "${evaluation.treatment}" with label "${evaluation.label}". ${parentName} evaluated treatment is part of [${acceptableTreatments}] ? ${matches}.`); return matches; } @@ -20,7 +20,7 @@ function checkTreatment(evaluation: IEvaluation, acceptableTreatments: string[], export default function dependencyMatcherContext({ split, treatments }: IDependencyMatcherData, storage: IStorageSync | IStorageAsync) { return function dependencyMatcher({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator): MaybeThenable { - log.debug(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? `\n attributes: ${JSON.stringify(attributes)}` : ''}`); + log.d(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? `\n attributes: ${JSON.stringify(attributes)}` : ''}`); const evaluation = splitEvaluator(key, split, attributes, storage); if (thenable(evaluation)) { diff --git a/src/evaluator/matchers/eq.ts b/src/evaluator/matchers/eq.ts index b01fda26..16a44f4c 100644 --- a/src/evaluator/matchers/eq.ts +++ b/src/evaluator/matchers/eq.ts @@ -5,7 +5,7 @@ export default function equalToMatcherContext(ruleAttr: number) /*: Function */ return function equalToMatcher(runtimeAttr: number): boolean { let isEqual = runtimeAttr === ruleAttr; - log.debug(`[equalToMatcher] is ${runtimeAttr} equal to ${ruleAttr}? ${isEqual}`); + log.d(`[equalToMatcher] is ${runtimeAttr} equal to ${ruleAttr}? ${isEqual}`); return isEqual; }; diff --git a/src/evaluator/matchers/eq_set.ts b/src/evaluator/matchers/eq_set.ts index d02c16a7..01c0a118 100644 --- a/src/evaluator/matchers/eq_set.ts +++ b/src/evaluator/matchers/eq_set.ts @@ -12,7 +12,7 @@ export default function equalToSetMatcherContext(ruleAttr: string[]) /*: Functio if (findIndex(ruleAttr, e => e === runtimeAttr[i]) < 0) isEqual = false; } - log.debug(`[equalToSetMatcher] is ${runtimeAttr} equal to set ${ruleAttr}? ${isEqual}`); + log.d(`[equalToSetMatcher] is ${runtimeAttr} equal to set ${ruleAttr}? ${isEqual}`); return isEqual; }; diff --git a/src/evaluator/matchers/ew.ts b/src/evaluator/matchers/ew.ts index 24185e06..86f57a04 100644 --- a/src/evaluator/matchers/ew.ts +++ b/src/evaluator/matchers/ew.ts @@ -6,7 +6,7 @@ export default function endsWithMatcherContext(ruleAttr: string[]) /*: Function return function endsWithMatcher(runtimeAttr: string): boolean { let endsWith = ruleAttr.some(e => strEndsWith(runtimeAttr, e)); - log.debug(`[endsWithMatcher] ${runtimeAttr} ends with ${ruleAttr}? ${endsWith}`); + log.d(`[endsWithMatcher] ${runtimeAttr} ends with ${ruleAttr}? ${endsWith}`); return endsWith; }; diff --git a/src/evaluator/matchers/gte.ts b/src/evaluator/matchers/gte.ts index 5afcbc00..c4374e48 100644 --- a/src/evaluator/matchers/gte.ts +++ b/src/evaluator/matchers/gte.ts @@ -5,7 +5,7 @@ export default function greaterThanEqualMatcherContext(ruleAttr: number) /*: Fun return function greaterThanEqualMatcher(runtimeAttr: number): boolean { let isGreaterEqualThan = runtimeAttr >= ruleAttr; - log.debug(`[greaterThanEqualMatcher] is ${runtimeAttr} greater than ${ruleAttr}? ${isGreaterEqualThan}`); + log.d(`[greaterThanEqualMatcher] is ${runtimeAttr} greater than ${ruleAttr}? ${isGreaterEqualThan}`); return isGreaterEqualThan; }; diff --git a/src/evaluator/matchers/lte.ts b/src/evaluator/matchers/lte.ts index bce0a915..84213ab7 100644 --- a/src/evaluator/matchers/lte.ts +++ b/src/evaluator/matchers/lte.ts @@ -5,7 +5,7 @@ export default function lessThanEqualMatcherContext(ruleAttr: number) /*: functi return function lessThanEqualMatcher(runtimeAttr: number): boolean { let isLessEqualThan = runtimeAttr <= ruleAttr; - log.debug(`[lessThanEqualMatcher] is ${runtimeAttr} less than ${ruleAttr}? ${isLessEqualThan}`); + log.d(`[lessThanEqualMatcher] is ${runtimeAttr} less than ${ruleAttr}? ${isLessEqualThan}`); return isLessEqualThan; }; diff --git a/src/evaluator/matchers/part_of.ts b/src/evaluator/matchers/part_of.ts index 238a7d97..0cd63b49 100644 --- a/src/evaluator/matchers/part_of.ts +++ b/src/evaluator/matchers/part_of.ts @@ -12,7 +12,7 @@ export default function partOfMatcherContext(ruleAttr: string[]) /*: Function */ if (findIndex(ruleAttr, e => e === runtimeAttr[i]) < 0) isPartOf = false; } - log.debug(`[partOfMatcher] ${runtimeAttr} is part of ${ruleAttr}? ${isPartOf}`); + log.d(`[partOfMatcher] ${runtimeAttr} is part of ${ruleAttr}? ${isPartOf}`); return isPartOf; }; diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index b4c67fdf..af05422b 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -11,12 +11,12 @@ export default function matcherSegmentContext(segmentName: string, storage: { se if (thenable(isInSegment)) { isInSegment.then(result => { - log.debug(`[asyncSegmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); + log.d(`[asyncSegmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); return result; }); } else { - log.debug(`[segmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); + log.d(`[segmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); } return isInSegment; diff --git a/src/evaluator/matchers/string.ts b/src/evaluator/matchers/string.ts index f885cb20..8df2a17e 100644 --- a/src/evaluator/matchers/string.ts +++ b/src/evaluator/matchers/string.ts @@ -8,14 +8,14 @@ export default function stringMatcherContext(ruleAttr: string) /*: Function */ { try { re = new RegExp(ruleAttr); } catch (e) { - log.debug(`[stringMatcher] ${ruleAttr} is an invalid regex`); + log.d(`[stringMatcher] ${ruleAttr} is an invalid regex`); return false; } let regexMatches = re.test(runtimeAttr); - log.debug(`[stringMatcher] does ${runtimeAttr} matches with ${ruleAttr}? ${regexMatches ? 'yes' : 'no'}`); + log.d(`[stringMatcher] does ${runtimeAttr} matches with ${ruleAttr}? ${regexMatches ? 'yes' : 'no'}`); return regexMatches; }; diff --git a/src/evaluator/matchers/sw.ts b/src/evaluator/matchers/sw.ts index 6e5f3962..39dbdcda 100644 --- a/src/evaluator/matchers/sw.ts +++ b/src/evaluator/matchers/sw.ts @@ -6,7 +6,7 @@ export default function startsWithMatcherContext(ruleAttr: string[]) /*: Functio return function startsWithMatcher(runtimeAttr: string): boolean { let matches = ruleAttr.some(e => startsWith(runtimeAttr, e)); - log.debug(`[startsWithMatcher] ${runtimeAttr} starts with ${ruleAttr}? ${matches}`); + log.d(`[startsWithMatcher] ${runtimeAttr} starts with ${ruleAttr}? ${matches}`); return matches; }; diff --git a/src/evaluator/matchers/whitelist.ts b/src/evaluator/matchers/whitelist.ts index fac0355d..de72a3a1 100644 --- a/src/evaluator/matchers/whitelist.ts +++ b/src/evaluator/matchers/whitelist.ts @@ -6,7 +6,7 @@ export default function whitelistMatcherContext(ruleAttr: ISet) /*: Func return function whitelistMatcher(runtimeAttr: string): boolean { let isInWhitelist = ruleAttr.has(runtimeAttr); - log.debug(`[whitelistMatcher] evaluated ${runtimeAttr} in [${setToArray(ruleAttr).join(',')}] => ${isInWhitelist}`); + log.d(`[whitelistMatcher] evaluated ${runtimeAttr} in [${setToArray(ruleAttr).join(',')}] => ${isInWhitelist}`); return isInWhitelist; }; diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index ba09b9b5..d3ccdded 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -9,9 +9,9 @@ function parseValue(key: string, attributeName: string | null, attributes: Split if (attributeName) { if (attributes) { value = attributes[attributeName]; - log.debug(`Extracted attribute [${attributeName}], [${value}] will be used for matching.`); + log.d(`Extracted attribute [${attributeName}], [${value}] will be used for matching.`); } else { - log.warn(`Defined attribute [${attributeName}], no attributes received.`); + log.w(`Defined attribute [${attributeName}], no attributes received.`); } } else { value = key; @@ -31,7 +31,7 @@ export default function value(key: string, matcherDto: IMatcherDto, attributes: if (sanitizedValue !== undefined) { return sanitizedValue; } else { - log.warn(`Value ${valueToMatch} ${attributeName ? `for attribute ${attributeName} ` : + ''}doesn't match with expected type.`); + log.w(`Value ${valueToMatch} ${attributeName ? `for attribute ${attributeName} ` : + ''}doesn't match with expected type.`); return; } } diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index 4f7a283a..ff014fd1 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -99,7 +99,7 @@ export default function sanitize(matcherTypeID: number, value: string | number | sanitizedValue = processor(sanitizedValue, attributes); } - log.debug(`Attempted to sanitize [${value}] which should be of type [${dataType}]. \n Sanitized and processed value => [${sanitizedValue instanceof Object ? JSON.stringify(sanitizedValue) : sanitizedValue}]`); + log.d(`Attempted to sanitize [${value}] which should be of type [${dataType}]. \n Sanitized and processed value => [${sanitizedValue instanceof Object ? JSON.stringify(sanitizedValue) : sanitizedValue}]`); return sanitizedValue; } diff --git a/src/integrations/ga/GaToSplit.ts b/src/integrations/ga/GaToSplit.ts index 1a95aea3..b1931121 100644 --- a/src/integrations/ga/GaToSplit.ts +++ b/src/integrations/ga/GaToSplit.ts @@ -167,7 +167,7 @@ export function fixEventTypeId(eventTypeId: any) { .replace(INVALID_PREFIX_REGEX, '') .replace(INVALID_SUBSTRING_REGEX, '_'); const truncated = fixed.slice(0, 80); - if (truncated.length < fixed.length) log.warn('EventTypeId was truncated because it cannot be more than 80 characters long.'); + if (truncated.length < fixed.length) log.w('EventTypeId was truncated because it cannot be more than 80 characters long.'); return truncated; } @@ -205,19 +205,19 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, sto const validIdentities = validateIdentities(opts.identities); if (validIdentities.length === 0) { - log.warn('No valid identities were provided. Please check that you are passing a valid list of identities or providing a traffic type at the SDK configuration.'); + log.w('No valid identities were provided. Please check that you are passing a valid list of identities or providing a traffic type at the SDK configuration.'); return; } const invalids = validIdentities.length - opts.identities.length; if (invalids) { - log.warn(`${invalids} identities were discarded because they are invalid or duplicated. Identities must be an array of objects with key and trafficType.`); + log.w(`${invalids} identities were discarded because they are invalid or duplicated. Identities must be an array of objects with key and trafficType.`); } opts.identities = validIdentities; // Validate prefix if (!isString(opts.prefix)) { - log.warn('The provided `prefix` was ignored since it is invalid. Please check that you are passing a string object as `prefix`.'); + log.w('The provided `prefix` was ignored since it is invalid. Please check that you are passing a string object as `prefix`.'); opts.prefix = undefined; } @@ -234,7 +234,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, sto try { if (opts.filter && !opts.filter(model)) return; } catch (err) { - log.warn(`GaToSplit custom filter threw: ${err}`); + log.w(`GaToSplit custom filter threw: ${err}`); return; } @@ -244,7 +244,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, sto try { eventData = opts.mapper(model, eventData as SplitIO.EventData); } catch (err) { - log.warn(`GaToSplit custom mapper threw: ${err}`); + log.w(`GaToSplit custom mapper threw: ${err}`); return; } if (!eventData) @@ -273,7 +273,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, sto } }); - log.info('Started GA-to-Split integration'); + log.i('Started GA-to-Split integration'); } } diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index e0fb82ea..d2417da1 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -60,7 +60,7 @@ export default class SplitToGa implements IIntegration { static validateFieldsObject(fieldsObject: any): fieldsObject is UniversalAnalytics.FieldsObject { if (fieldsObject && fieldsObject.hitType) return true; - log.warn('your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.'); + log.w('your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.'); return false; } @@ -85,8 +85,8 @@ export default class SplitToGa implements IIntegration { this.events = options.events; } - log.info('Started Split-to-GA integration'); - if (typeof SplitToGa.getGa() !== 'function') log.warn(noGaWarning + ' No hits will be sent until it is available.'); + log.i('Started Split-to-GA integration'); + if (typeof SplitToGa.getGa() !== 'function') log.w(noGaWarning + ' No hits will be sent until it is available.'); } queue(data: SplitIO.IntegrationData) { @@ -111,7 +111,7 @@ export default class SplitToGa implements IIntegration { if (!fieldsObject || !SplitToGa.validateFieldsObject(fieldsObject)) return; } } catch (err) { - log.warn(`SplitToGa queue method threw: ${err}. No hit was sent.`); + log.w(`SplitToGa queue method threw: ${err}. No hit was sent.`); return; } @@ -124,7 +124,7 @@ export default class SplitToGa implements IIntegration { ga(sendCommand, fieldsObject); }); } else { - log.warn(noGaWarning + ' No hit was sent.'); + log.w(noGaWarning + ' No hit was sent.'); } } diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index fd6a3829..c99729f7 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -86,7 +86,7 @@ describe('SplitToGa', () => { let integration = new SplitToGa(); expect(typeof integration).toBe('object'); - expect(loggerMock.warn.mock.calls.length).toBe(0); + expect(loggerMock.w.mock.calls.length).toBe(0); gaRemove(); expect(SplitToGa.getGa()).toBe(undefined); // should return undefined if ga command queue does not exist @@ -95,7 +95,7 @@ describe('SplitToGa', () => { expect(typeof integration).toBe('object'); // SplitToGa instances should be created even if ga command queue does not exist // @ts-expect-error integration.queue('fake-data'); - expect(loggerMock.warn.mock.calls).toEqual([ // Warn when creating and queueing while ga command queue does not exist + expect(loggerMock.w.mock.calls).toEqual([ // Warn when creating and queueing while ga command queue does not exist ['`ga` command queue not found. No hits will be sent until it is available.'], ['`ga` command queue not found. No hit was sent.'] ]); diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index e7a47ce5..caa27a18 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -41,7 +41,7 @@ export default class BrowserSignalListener implements ISignalListener { */ start() { if (typeof window !== 'undefined' && window.addEventListener) { - log.debug('Registering flush handler when unload page event is triggered.'); + log.d('Registering flush handler when unload page event is triggered.'); window.addEventListener(UNLOAD_DOM_EVENT, this.flushData); } } @@ -53,7 +53,7 @@ export default class BrowserSignalListener implements ISignalListener { */ stop() { if (typeof window !== 'undefined' && window.removeEventListener) { - log.debug('Deregistering flush handler when unload page event is triggered.'); + log.d('Deregistering flush handler when unload page event is triggered.'); window.removeEventListener(UNLOAD_DOM_EVENT, this.flushData); } } diff --git a/src/listeners/node.ts b/src/listeners/node.ts index 5e9a10c1..42e8a965 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -21,13 +21,13 @@ export default class NodeSignalListener implements ISignalListener { } start() { - log.debug('Registering cleanup handlers.'); + log.d('Registering cleanup handlers.'); // eslint-disable-next-line no-undef process.on('SIGTERM', this._sigtermHandler); } stop() { - log.debug('Deregistering cleanup handlers.'); + log.d('Deregistering cleanup handlers.'); // eslint-disable-next-line no-undef process.removeListener('SIGTERM', this._sigtermHandler); } @@ -45,14 +45,14 @@ export default class NodeSignalListener implements ISignalListener { process.kill(process.pid, 'SIGTERM'); }; - log.debug('Split SDK graceful shutdown after SIGTERM.'); + log.d('Split SDK graceful shutdown after SIGTERM.'); let handlerResult = null; try { handlerResult = this.handler(); } catch (err) { - log.error(`Error with Split graceful shutdown: ${err}`); + log.e(`Error with Split graceful shutdown: ${err}`); } if (thenable(handlerResult)) { diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index 4ab2d782..cc01c897 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -34,10 +34,10 @@ test('SPLIT LOGGER / Logger class shape', () => { const logger = new Logger('test-category', {}); - expect(typeof logger.debug).toBe('function'); // instance.debug should be a method. - expect(typeof logger.info).toBe('function'); // instance.info should be a method. - expect(typeof logger.warn).toBe('function'); // instance.warn should be a method. - expect(typeof logger.error).toBe('function'); // instance.error should be a method. + expect(typeof logger.d).toBe('function'); // instance.d should be a method. + expect(typeof logger.i).toBe('function'); // instance.i should be a method. + expect(typeof logger.w).toBe('function'); // instance.w should be a method. + expect(typeof logger.e).toBe('function'); // instance.e should be a method. }); @@ -60,7 +60,7 @@ function testLogLevels(levelToTest: string) { const runTests = (showLevel?: boolean, displayAllErrors?: boolean) => { let logLevelLogsCounter = 0; let testForNoLog = false; - const logMethod = levelToTest.toLowerCase(); + const logMethod = levelToTest.toLowerCase().charAt(0); const logCategory = `test-category-${logMethod}${displayAllErrors ? 'displayAllErrors' : ''}`; const instance = new Logger(logCategory, { showLevel, displayAllErrors @@ -71,7 +71,7 @@ function testLogLevels(levelToTest: string) { const expectedMessage = buildExpectedMessage(levelToTest, logCategory, logMsg, showLevel); // Log error should always be visible. - if (logMethod === LOG_LEVELS.ERROR.toLowerCase() && displayAllErrors) testForNoLog = false; + if (logMethod === LOG_LEVELS.ERROR.toLowerCase().charAt(0) && displayAllErrors) testForNoLog = false; // Set the logLevel for this iteration. setLogLevel(LogLevels[logLevel]); @@ -105,22 +105,22 @@ function testLogLevels(levelToTest: string) { } -test('SPLIT LOGGER / Logger class public methods behaviour - instance.debug', () => { +test('SPLIT LOGGER / Logger class public methods behaviour - instance.d', () => { testLogLevels(LogLevels.DEBUG); }); -test('SPLIT LOGGER / Logger class public methods behaviour - instance.info', () => { +test('SPLIT LOGGER / Logger class public methods behaviour - instance.i', () => { testLogLevels(LogLevels.INFO); }); -test('SPLIT LOGGER / Logger class public methods behaviour - instance.warn', () => { +test('SPLIT LOGGER / Logger class public methods behaviour - instance.w', () => { testLogLevels(LogLevels.WARN); }); -test('SPLIT LOGGER / Logger class public methods behaviour - instance.error', () => { +test('SPLIT LOGGER / Logger class public methods behaviour - instance.e', () => { testLogLevels(LogLevels.ERROR); }); diff --git a/src/logger/__tests__/sdkLogger.mock.ts b/src/logger/__tests__/sdkLogger.mock.ts index 0ba6aa71..e8eff067 100644 --- a/src/logger/__tests__/sdkLogger.mock.ts +++ b/src/logger/__tests__/sdkLogger.mock.ts @@ -7,17 +7,17 @@ jest.mock('../sdkLogger'); import { logFactory } from '../sdkLogger'; export const loggerMock = { - warn: jest.fn(), - error: jest.fn(), - debug: jest.fn(), - info: jest.fn(), + w: jest.fn(), + e: jest.fn(), + d: jest.fn(), + i: jest.fn(), }; (logFactory as jest.Mock).mockReturnValue(loggerMock); export function mockClear() { - loggerMock.warn.mockClear(); - loggerMock.error.mockClear(); - loggerMock.debug.mockClear(); - loggerMock.info.mockClear(); + loggerMock.w.mockClear(); + loggerMock.e.mockClear(); + loggerMock.d.mockClear(); + loggerMock.i.mockClear(); } diff --git a/src/logger/index.ts b/src/logger/index.ts index e80cffe0..166b9159 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -36,22 +36,22 @@ export class Logger { this.options = objectAssign({}, defaultOptions, options); } - debug(msg: string) { + d(msg: string) { if (this._shouldLog(LogLevels.DEBUG)) this._log(LogLevels.DEBUG, msg); } - info(msg: string) { + i(msg: string) { if (this._shouldLog(LogLevels.INFO)) this._log(LogLevels.INFO, msg); } - warn(msg: string) { + w(msg: string) { if (this._shouldLog(LogLevels.WARN)) this._log(LogLevels.WARN, msg); } - error(msg: string) { + e(msg: string) { if (this.options.displayAllErrors || this._shouldLog(LogLevels.ERROR)) this._log(LogLevels.ERROR, msg); } diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index a7dbe9a8..0e0ab37e 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -52,7 +52,7 @@ export const API: ILoggerAPI = { if (isLogLevelString(logLevel)) { setLogLevel(logLevel); } else { - ownLog.error('Invalid Log Level - No changes to the logs will be applied.'); + ownLog.e('Invalid Log Level - No changes to the logs will be applied.'); } }, /** diff --git a/src/readiness/__tests__/sdkReadinessManager.spec.ts b/src/readiness/__tests__/sdkReadinessManager.spec.ts index 14418694..3d6b1d6f 100644 --- a/src/readiness/__tests__/sdkReadinessManager.spec.ts +++ b/src/readiness/__tests__/sdkReadinessManager.spec.ts @@ -82,8 +82,8 @@ describe('SDK Readiness Manager - Event emitter', () => { const readyFromCacheEventCB = gateMock.once.mock.calls[2][1]; readyFromCacheEventCB(); - expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY_FROM_CACHE event fires, we get a info message. - expect(loggerMock.info.mock.calls[0]).toEqual(['Split SDK is ready from cache.']); // Telling us the SDK is ready to be used with data from cache. + expect(loggerMock.i.mock.calls.length).toBe(1); // If the SDK_READY_FROM_CACHE event fires, we get a info message. + expect(loggerMock.i.mock.calls[0]).toEqual(['Split SDK is ready from cache.']); // Telling us the SDK is ready to be used with data from cache. }); test('The event callbacks should work as expected - SDK_READY emits with no callbacks', () => { @@ -94,19 +94,19 @@ describe('SDK Readiness Manager - Event emitter', () => { emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls.length).toBe(1); // If the SDK_READY event fires and we have no callbacks for it (neither event nor ready promise) we get a warning. - expect(loggerMock.warn.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // Telling us there were no listeners and evaluations before this point may have been incorrect. + expect(loggerMock.w.mock.calls.length).toBe(1); // If the SDK_READY event fires and we have no callbacks for it (neither event nor ready promise) we get a warning. + expect(loggerMock.w.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // Telling us there were no listeners and evaluations before this point may have been incorrect. // Now it's marked as ready. addListenerCB('this event we do not care'); - expect(loggerMock.error.mock.calls.length).toBe(0); // Now if we add a listener to an event unrelated with readiness, we get no errors logged. + expect(loggerMock.e.mock.calls.length).toBe(0); // Now if we add a listener to an event unrelated with readiness, we get no errors logged. addListenerCB(SDK_READY); - expect(loggerMock.error.mock.calls).toEqual([['A listener was added for SDK_READY on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY we get the corresponding warning. + expect(loggerMock.e.mock.calls).toEqual([['A listener was added for SDK_READY on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY we get the corresponding warning. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); addListenerCB(SDK_READY_TIMED_OUT); - expect(loggerMock.error.mock.calls).toEqual([['A listener was added for SDK_READY_TIMED_OUT on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY_TIMED_OUT we get the corresponding warning. + expect(loggerMock.e.mock.calls).toEqual([['A listener was added for SDK_READY_TIMED_OUT on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY_TIMED_OUT we get the corresponding warning. }); test('The event callbacks should work as expected - SDK_READY emits with callbacks', () => { @@ -116,12 +116,12 @@ describe('SDK Readiness Manager - Event emitter', () => { const addListenerCB = sdkReadinessManager.readinessManager.gate.on.mock.calls[1][1]; addListenerCB(SDK_READY); - expect(loggerMock.warn.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no warnings are logged. - expect(loggerMock.error.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no errors are logged. + expect(loggerMock.w.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no warnings are logged. + expect(loggerMock.e.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no errors are logged. emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls.length).toBe(0); // As we had at least one listener, we get no warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // As we had at least one listener, we get no warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { @@ -141,7 +141,7 @@ describe('SDK Readiness Manager - Event emitter', () => { removeListenerCB(SDK_READY); emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // We get the warning. + expect(loggerMock.w.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // We get the warning. }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { @@ -162,7 +162,7 @@ describe('SDK Readiness Manager - Event emitter', () => { removeListenerCB('random event'); emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls.length).toBe(0); // No warning when the SDK is ready as we still have one listener. + expect(loggerMock.w.mock.calls.length).toBe(0); // No warning when the SDK is ready as we still have one listener. }); test('The event callbacks should work as expected - SDK_READY emits with expected internal callbacks', () => { @@ -179,12 +179,12 @@ describe('SDK Readiness Manager - Event emitter', () => { addListenerCB(SDK_READY); removeListenerCB(SDK_READY); - expect(loggerMock.warn.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no warnings are logged. - expect(loggerMock.error.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no errors are logged. + expect(loggerMock.w.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no warnings are logged. + expect(loggerMock.e.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no errors are logged. emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls.length).not.toBe(0); // As we had the same amount of listeners that the expected, we get a warning. - expect(loggerMock.error.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. + expect(loggerMock.w.mock.calls.length).not.toBe(0); // As we had the same amount of listeners that the expected, we get a warning. + expect(loggerMock.e.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. }); }); @@ -267,8 +267,8 @@ describe('SDK Readiness Manager - Ready promise', () => { const readyEventCB = sdkReadinessManager.readinessManager.gate.once.mock.calls[0][1]; readyEventCB(); - expect(loggerMock.warn.mock.calls).toEqual([['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']]); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise. - loggerMock.warn.mockClear(); + expect(loggerMock.w.mock.calls).toEqual([['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']]); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise. + loggerMock.w.mockClear(); readyPromise.then(() => { expect('The ready promise is resolved when the gate emits SDK_READY.'); @@ -278,7 +278,7 @@ describe('SDK Readiness Manager - Ready promise', () => { }); readyEventCB(); - expect(loggerMock.warn.mock.calls.length).toBe(0); // But if we have a listener there are no warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // But if we have a listener there are no warnings. }); test('.ready() rejected promises have a default onRejected handler that just logs the error', (done) => { @@ -291,14 +291,14 @@ describe('SDK Readiness Manager - Ready promise', () => { () => { throw new Error('It should be a promise that was rejected on SDK_READY_TIMED_OUT, not resolved.'); } ); - expect(loggerMock.error.mock.calls.length === 0).toBe(true); // not called until promise is rejected + expect(loggerMock.e.mock.calls.length === 0).toBe(true); // not called until promise is rejected setTimeout(() => { - expect(loggerMock.error.mock.calls).toEqual([[timeoutErrorMessage]]); // If we don\'t handle the rejected promise, an error is logged. + expect(loggerMock.e.mock.calls).toEqual([[timeoutErrorMessage]]); // If we don\'t handle the rejected promise, an error is logged. readyForTimeout = sdkReadinessManager.sdkStatus.ready(); setTimeout(() => { - expect(loggerMock.error).lastCalledWith('Split SDK has emitted SDK_READY_TIMED_OUT event.'); // If we don\'t handle a new .ready() rejected promise, an error is logged. + expect(loggerMock.e).lastCalledWith('Split SDK has emitted SDK_READY_TIMED_OUT event.'); // If we don\'t handle a new .ready() rejected promise, an error is logged. readyForTimeout = sdkReadinessManager.sdkStatus.ready(); readyForTimeout @@ -306,7 +306,7 @@ describe('SDK Readiness Manager - Ready promise', () => { .then(() => { throw new Error(); }) .catch((error) => { expect(error).toBe('Split SDK has emitted SDK_READY_TIMED_OUT event.'); - expect(loggerMock.error).toBeCalledTimes(2); // If we provide an onRejected handler, even chaining several onFulfilled handlers, the error is not logged. + expect(loggerMock.e).toBeCalledTimes(2); // If we provide an onRejected handler, even chaining several onFulfilled handlers, the error is not logged. done(); }); }, 0); diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index 551b26c5..705eebf8 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -17,7 +17,7 @@ const REMOVE_LISTENER_EVENT = 'removeListener'; // default onRejected handler, that just logs the error, if ready promise doesn't have one. function defaultOnRejected(err: any) { - log.error(err); + log.e(err); } /** @@ -44,7 +44,7 @@ export default function sdkReadinessManagerFactory( readinessManager.gate.on(NEW_LISTENER_EVENT, (event: any) => { if (event === SDK_READY || event === SDK_READY_TIMED_OUT) { if (readinessManager.isReady()) { - log.error(`A listener was added for ${event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT'} on the SDK, which has already fired and won't be emitted again. The callback won't be executed.`); + log.e(`A listener was added for ${event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT'} on the SDK, which has already fired and won't be emitted again. The callback won't be executed.`); } else if (event === SDK_READY) { readyCbCount++; } @@ -55,13 +55,13 @@ export default function sdkReadinessManagerFactory( const readyPromise = generateReadyPromise(); readinessManager.gate.once(SDK_READY_FROM_CACHE, () => { - log.info('Split SDK is ready from cache.'); + log.i('Split SDK is ready from cache.'); }); function generateReadyPromise() { const promise = promiseWrapper(new Promise((resolve, reject) => { readinessManager.gate.once(SDK_READY, () => { - if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn('No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'); + if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.w('No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'); resolve(); }); readinessManager.gate.once(SDK_READY_TIMED_OUT, reject); diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index 9f66f9e8..e3aed544 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -76,10 +76,10 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl } const { treatment, label, changeNumber, config = null } = evaluation; - log.info(`Split: ${splitName}. Key: ${matchingKey}. Evaluation: ${treatment}. Label: ${label}`); + log.i(`Split: ${splitName}. Key: ${matchingKey}. Evaluation: ${treatment}. Label: ${label}`); if (validateSplitExistance(readinessManager, splitName, label, invokingMethodName)) { - log.info('Queueing corresponding impression.'); + log.i('Queueing corresponding impression.'); queue.push({ feature: splitName, keyName: matchingKey, diff --git a/src/sdkClient/sdkClientMethod.ts b/src/sdkClient/sdkClientMethod.ts index 0933916a..be1a2dd5 100644 --- a/src/sdkClient/sdkClientMethod.ts +++ b/src/sdkClient/sdkClientMethod.ts @@ -16,7 +16,7 @@ export function sdkClientMethodFactory(params: ISdkClientFactoryParams): () => S throw new Error('Shared Client not supported by the storage mechanism. Create isolated instances instead.'); } - log.debug('Retrieving SDK client.'); + log.d('Retrieving SDK client.'); return clientInstance; }; } diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index f2490aae..3012b854 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -41,7 +41,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? return function client(key?: SplitIO.SplitKey) { if (key === undefined) { - log.debug('Retrieving default SDK client.'); + log.d('Retrieving default SDK client.'); return mainClientInstance; } @@ -75,9 +75,9 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? sharedSyncManager.start(); - log.info('New shared client instance created.'); + log.i('New shared client instance created.'); } else { - log.debug('Retrieving existing SDK client.'); + log.d('Retrieving existing SDK client.'); } return clientInstances[instanceId]; diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index b49df093..a85e7852 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -48,7 +48,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? return function client(key?: SplitIO.SplitKey, trafficType?: string) { if (key === undefined) { - log.debug('Retrieving default SDK client.'); + log.d('Retrieving default SDK client.'); return mainClientInstance; } @@ -90,9 +90,9 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? sharedSyncManager.start(); - log.info('New shared client instance created.'); + log.i('New shared client instance created.'); } else { - log.debug('Retrieving existing SDK client.'); + log.d('Retrieving existing SDK client.'); } return clientInstances[instanceId]; diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 1db36dd2..568c2038 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -77,7 +77,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. syncManager && syncManager.start(); signalListener && signalListener.start(); - log.info('New Split SDK instance created.'); + log.i('New Split SDK instance created.'); return { // Split evaluation and event tracking engine @@ -86,8 +86,8 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // Manager API to explore available information // @ts-ignore manager() { - if (managerInstance) log.info('Manager instance retrieved.'); - else log.error('Manager instance is not available. Provide the manager module on settings.'); + if (managerInstance) log.i('Manager instance retrieved.'); + else log.e('Manager instance is not available. Provide the manager module on settings.'); return managerInstance; }, diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index 116e5323..267d31e0 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -21,7 +21,7 @@ export function splitHttpClientFactory(apikey: string, metadata: IMetadata, getF const fetch = getFetch && getFetch(); // if fetch is not available, log Error - if (!fetch) log.error(messageNoFetch + ' The SDK will not get ready.'); + if (!fetch) log.e(messageNoFetch + ' The SDK will not get ready.'); const headers: Record = { 'Accept': 'application/json', @@ -62,7 +62,7 @@ export function splitHttpClientFactory(apikey: string, metadata: IMetadata, getF } if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else. - log[logErrorsAsInfo ? 'info' : 'error'](`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); + log[logErrorsAsInfo ? 'i' : 'e'](`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); } // passes `undefined` as statusCode if not an HTTP error (resp === undefined) diff --git a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts index 6f93eba7..c13f4e44 100644 --- a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +++ b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts @@ -20,7 +20,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { * @NOTE this method is not being used at the moment. */ clear() { - log.info('Flushing MySegments data from localStorage'); + log.i('Flushing MySegments data from localStorage'); // We cannot simply call `localStorage.clear()` since that implies removing user items from the storage // We could optimize next sentence, since it implies iterating over all localStorage items @@ -34,7 +34,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { localStorage.setItem(segmentKey, DEFINED); return true; } catch (e) { - log.error(e); + log.e(e); return false; } } @@ -46,7 +46,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { localStorage.removeItem(segmentKey); return true; } catch (e) { - log.error(e); + log.e(e); return false; } } diff --git a/src/storages/inLocalStorage/SplitsCacheInLocal.ts b/src/storages/inLocalStorage/SplitsCacheInLocal.ts index 742ee1c4..7067b67f 100644 --- a/src/storages/inLocalStorage/SplitsCacheInLocal.ts +++ b/src/storages/inLocalStorage/SplitsCacheInLocal.ts @@ -52,7 +52,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { } } } catch (e) { - log.error(e); + log.e(e); } } @@ -72,7 +72,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { } } } catch (e) { - log.error(e); + log.e(e); } } @@ -82,7 +82,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { * We cannot simply call `localStorage.clear()` since that implies removing user items from the storage. */ clear() { - log.info('Flushing Splits data from localStorage'); + log.i('Flushing Splits data from localStorage'); // collect item keys const len = localStorage.length; @@ -114,7 +114,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { return true; } catch (e) { - log.error(e); + log.e(e); return false; } } @@ -129,7 +129,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { return 1; } catch (e) { - log.error(e); + log.e(e); return 0; } } @@ -147,14 +147,14 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { // when using a new split query, we must update it at the store if (this.updateNewFilter) { - log.info('Split filter query was modified. Updating cache.'); + log.i('Split filter query was modified. Updating cache.'); const queryKey = this.keys.buildSplitsFilterQueryKey(); const queryString = this.splitFiltersValidation.queryString; try { if (queryString) localStorage.setItem(queryKey, queryString); else localStorage.removeItem(queryKey); } catch (e) { - log.error(e); + log.e(e); } this.updateNewFilter = false; } @@ -166,7 +166,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { this.hasSync = true; return true; } catch (e) { - log.error(e); + log.e(e); return false; } } @@ -273,7 +273,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { }); } } catch (e) { - log.error(e); + log.e(e); } } // if the filter didn't change, nothing is done diff --git a/src/storages/inLocalStorage/index.ts b/src/storages/inLocalStorage/index.ts index 6eb1fcf8..415e4196 100644 --- a/src/storages/inLocalStorage/index.ts +++ b/src/storages/inLocalStorage/index.ts @@ -23,7 +23,7 @@ export function InLocalStorage(options: InLocalStorageOptions = {}) { // Fallback to InMemoryStorage if LocalStorage API is not available if (!isLocalStorageAvailable()) { - log.warn('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); + log.w('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); return; } diff --git a/src/storages/inRedis/EventsCacheInRedis.ts b/src/storages/inRedis/EventsCacheInRedis.ts index e0fda5bc..fc6ffa5c 100644 --- a/src/storages/inRedis/EventsCacheInRedis.ts +++ b/src/storages/inRedis/EventsCacheInRedis.ts @@ -32,7 +32,7 @@ export default class EventsCacheInRedis implements IEventsCacheAsync { // We use boolean values to signal successful queueing .then(() => true) .catch(err => { - log.error(`Error adding event to queue: ${err}.`); + log.e(`Error adding event to queue: ${err}.`); return false; }); } diff --git a/src/storages/inRedis/RedisAdapter.ts b/src/storages/inRedis/RedisAdapter.ts index a27f7b4f..0ff1b73e 100644 --- a/src/storages/inRedis/RedisAdapter.ts +++ b/src/storages/inRedis/RedisAdapter.ts @@ -52,16 +52,16 @@ export default class RedisAdapter extends ioredis { _listenToEvents() { this.once('ready', () => { const commandsCount = this._notReadyCommandsQueue ? this._notReadyCommandsQueue.length : 0; - log.info(`Redis connection established. Queued commands: ${commandsCount}.`); + log.i(`Redis connection established. Queued commands: ${commandsCount}.`); this._notReadyCommandsQueue && this._notReadyCommandsQueue.forEach(queued => { - log.info(`Executing queued ${queued.name} command.`); + log.i(`Executing queued ${queued.name} command.`); queued.command().then(queued.resolve).catch(queued.reject); }); // After the SDK is ready for the first time we'll stop queueing commands. This is just so we can keep handling BUR for them. this._notReadyCommandsQueue = undefined; }); this.once('close', () => { - log.info('Redis connection closed.'); + log.i('Redis connection closed.'); }); } @@ -75,7 +75,7 @@ export default class RedisAdapter extends ioredis { const params = arguments; function commandWrapper() { - log.debug(`Executing ${method}.`); + log.d(`Executing ${method}.`); // Return original method const result = originalMethod.apply(instance, params); @@ -90,7 +90,7 @@ export default class RedisAdapter extends ioredis { result.then(cleanUpRunningCommandsCb, cleanUpRunningCommandsCb); return timeout(instance._options.operationTimeout, result).catch(err => { - log.error(`${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`); + log.e(`${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`); // Handling is not the adapter responsibility. throw err; }); @@ -123,19 +123,19 @@ export default class RedisAdapter extends ioredis { setTimeout(function deferedDisconnect() { if (instance._runningCommands.size > 0) { - log.info(`Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`); + log.i(`Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`); Promise.all(setToArray(instance._runningCommands)) .then(() => { - log.debug('Pending commands finished successfully, disconnecting.'); + log.d('Pending commands finished successfully, disconnecting.'); originalMethod.apply(instance, params); }) .catch(e => { - log.warn(`Pending commands finished with error: ${e}. Proceeding with disconnection.`); + log.w(`Pending commands finished with error: ${e}. Proceeding with disconnection.`); originalMethod.apply(instance, params); }); } else { - log.debug('No commands pending execution, disconnect.'); + log.d('No commands pending execution, disconnect.'); // Nothing pending, just proceed. originalMethod.apply(instance, params); } diff --git a/src/storages/inRedis/SplitsCacheInRedis.ts b/src/storages/inRedis/SplitsCacheInRedis.ts index bd5de621..5bfc8bd4 100644 --- a/src/storages/inRedis/SplitsCacheInRedis.ts +++ b/src/storages/inRedis/SplitsCacheInRedis.ts @@ -82,7 +82,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { */ getSplit(name: string): Promise { if (this.redisError) { - log.error(this.redisError); + log.e(this.redisError); throw this.redisError; } @@ -136,14 +136,14 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { .then((ttCount: string | null | number) => { ttCount = parseInt(ttCount as string, 10); if (!isFiniteNumber(ttCount) || ttCount < 0) { - log.info(`Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`); + log.i(`Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`); return false; } return ttCount > 0; }) .catch(e => { - log.error(`Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`); + log.e(`Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`); // If there is an error, bypass the validation so the event can get tracked. return true; }); @@ -168,7 +168,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { */ getSplits(names: string[]): Promise> { if (this.redisError) { - log.error(this.redisError); + log.e(this.redisError); throw this.redisError; } @@ -182,7 +182,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { return Promise.resolve(splits); }) .catch(e => { - log.error(`Could not grab splits due to an error: ${e}.`); + log.e(`Could not grab splits due to an error: ${e}.`); return Promise.reject(e); }); } diff --git a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts index 77f34a12..448191c2 100644 --- a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts +++ b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts @@ -182,21 +182,21 @@ test('STORAGE Redis Adapter / instance methods - _listenToEvents', (done) => { expect(secondCallArgs[0]).toBe('close'); // First argument for the first call should be the "close" event. expect(typeof secondCallArgs[1]).toBe('function'); // second argument for the first call should be a callback function. - expect(loggerMock.warn.mock.calls.length).toBe(0); // Control assertion + expect(loggerMock.w.mock.calls.length).toBe(0); // Control assertion secondCallArgs[1](); // Execute the callback for "close" - expect(loggerMock.info.mock.calls.length).toBe(1); // The callback for the "close" event will only log info to the user about what is going on. - expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection closed.']); // The callback for the "close" event will only log info to the user about what is going on. + expect(loggerMock.i.mock.calls.length).toBe(1); // The callback for the "close" event will only log info to the user about what is going on. + expect(loggerMock.i.mock.calls[0]).toEqual(['Redis connection closed.']); // The callback for the "close" event will only log info to the user about what is going on. - loggerMock.info.mockClear(); - expect(loggerMock.info.mock.calls.length).toBe(0); // Control assertion + loggerMock.i.mockClear(); + expect(loggerMock.i.mock.calls.length).toBe(0); // Control assertion expect(Array.isArray(instance._notReadyCommandsQueue)).toBe(true); // Control assertion // Without any offline commands queued, execute the callback for "ready" firstCallArgs[1](); - expect(loggerMock.info.mock.calls.length).not.toBe(0); // The callback for the "ready" event will inform the user about the trigger. - expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection established. Queued commands: 0.']); // The callback for the "ready" event will inform the user about the trigger. + expect(loggerMock.i.mock.calls.length).not.toBe(0); // The callback for the "ready" event will inform the user about the trigger. + expect(loggerMock.i.mock.calls[0]).toEqual(['Redis connection established. Queued commands: 0.']); // The callback for the "ready" event will inform the user about the trigger. expect(instance._notReadyCommandsQueue).toBe(undefined); // After the DB is ready, it will clean up the offline commands queue so we do not queue commands anymore. // Don't do this at home @@ -213,13 +213,13 @@ test('STORAGE Redis Adapter / instance methods - _listenToEvents', (done) => { reject: jest.fn() }; instance._notReadyCommandsQueue = [queuedGetCommand, queuedSetCommand]; - loggerMock.info.mockClear(); + loggerMock.i.mockClear(); // execute the callback for "ready" once more firstCallArgs[1](); - expect(loggerMock.info.mock.calls.length).toBe(3); // If we had queued commands, it will log the event (1 call) as well as each executed command (n calls). - expect(loggerMock.info.mock.calls).toEqual([ + expect(loggerMock.i.mock.calls.length).toBe(3); // If we had queued commands, it will log the event (1 call) as well as each executed command (n calls). + expect(loggerMock.i.mock.calls).toEqual([ ['Redis connection established. Queued commands: 2.'], // The callback for the "ready" event will inform the user about the trigger and the amount of queued commands. ['Executing queued GET command.'], // If we had queued, it will log the event as well as each executed command. ['Executing queued SET command.'] // If we had queued commands, it will log the event as well as each executed command. @@ -263,7 +263,7 @@ test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queuein }); instance._notReadyCommandsQueue = false; // Remove the queue. - loggerMock.error.resetHistory; + loggerMock.e.resetHistory; forEach(METHODS_TO_PROMISE_WRAP, (methodName, index) => { // We do NOT have the commands queue on this state, so a call for this methods will execute the command. @@ -286,7 +286,7 @@ test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queuein commandTimeoutResolver.rej('test'); setTimeout(() => { // Allow the promises to tick. expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes with error, it's promise is removed from the instance._runningCommands queue. - expect(loggerMock.error.mock.calls[index]).toEqual([`${methodName} operation threw an error or exceeded configured timeout of 5000ms. Message: test`]); // The log error method should be called with the corresponding messages, depending on the method, error and operationTimeout. + expect(loggerMock.e.mock.calls[index]).toEqual([`${methodName} operation threw an error or exceeded configured timeout of 5000ms. Message: test`]); // The log error method should be called with the corresponding messages, depending on the method, error and operationTimeout. }, 0); }); @@ -312,7 +312,7 @@ test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queuein commandTimeoutResolver.res('test'); setTimeout(() => { // Allow the promises to tick. - expect(loggerMock.error.mock.calls.length).toBe(0); // No error should be logged + expect(loggerMock.e.mock.calls.length).toBe(0); // No error should be logged expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes successfully, it's promise is removed from the instance._runningCommands queue. }, 0); }); @@ -337,9 +337,9 @@ test('STORAGE Redis Adapter / instance methods - _setDisconnectWrapper', (done) expect(ioredisMock.disconnect.mock.calls.length).toBe(0); // Original method should not be called right away. setTimeout(() => { // o queued commands timeout wrapper. - expect(loggerMock.debug.mock.calls).toEqual([['No commands pending execution, disconnect.']]); + expect(loggerMock.d.mock.calls).toEqual([['No commands pending execution, disconnect.']]); expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously - loggerMock.debug.mockClear(); + loggerMock.d.mockClear(); ioredisMock.disconnect.mockClear(); // Second run, two pending commands, one will fail. @@ -350,15 +350,15 @@ test('STORAGE Redis Adapter / instance methods - _setDisconnectWrapper', (done) rejectedPromise.catch(() => { }); // Swallow the unhandled to avoid unhandledRejection warns setTimeout(() => { // queued with rejection timeout wrapper - expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 2 commands still waiting for resolution. Defering disconnection until those finish.']]); + expect(loggerMock.i.mock.calls).toEqual([['Attempting to disconnect but there are 2 commands still waiting for resolution. Defering disconnection until those finish.']]); Promise.all(setToArray(instance._runningCommands)).catch(e => { setImmediate(() => { // Allow the callback to execute before checking. - expect(loggerMock.warn.mock.calls[0]).toEqual([`Pending commands finished with error: ${e}. Proceeding with disconnection.`]); // Should warn about the error but tell user that will disconnect anyways. + expect(loggerMock.w.mock.calls[0]).toEqual([`Pending commands finished with error: ${e}. Proceeding with disconnection.`]); // Should warn about the error but tell user that will disconnect anyways. expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously - loggerMock.info.mockClear(); - loggerMock.warn.mockClear(); + loggerMock.i.mockClear(); + loggerMock.w.mockClear(); ioredisMock.disconnect.mockClear(); // Third run, pending commands all successful @@ -370,11 +370,11 @@ test('STORAGE Redis Adapter / instance methods - _setDisconnectWrapper', (done) instance._runningCommands.add(Promise.resolve()); setTimeout(() => { - expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 4 commands still waiting for resolution. Defering disconnection until those finish.']]); + expect(loggerMock.i.mock.calls).toEqual([['Attempting to disconnect but there are 4 commands still waiting for resolution. Defering disconnection until those finish.']]); Promise.all(setToArray(instance._runningCommands)).then(() => { // This one will go through success path setImmediate(() => { - expect(loggerMock.debug.mock.calls).toEqual([['Pending commands finished successfully, disconnecting.']]); + expect(loggerMock.d.mock.calls).toEqual([['Pending commands finished successfully, disconnecting.']]); expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously }); }); diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index 9d5bf70d..75390064 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -47,7 +47,7 @@ function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath): false | try { data = fs.readFileSync(filePath, 'utf-8'); } catch (e) { - log.error(e.message); + log.e(e.message); return {}; } @@ -59,12 +59,12 @@ function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath): false | let tuple: string | string[] = line.trim(); if (tuple === '' || tuple.charAt(0) === '#') { - log.debug(`Ignoring empty line or comment at #${index}`); + log.d(`Ignoring empty line or comment at #${index}`); } else { tuple = tuple.split(/\s+/); if (tuple.length !== 2) { - log.debug(`Ignoring line since it does not have exactly two columns #${index}`); + log.d(`Ignoring line since it does not have exactly two columns #${index}`); } else { const splitName = tuple[SPLIT_POSITION]; const condition = parseCondition({ treatment: tuple[TREATMENT_POSITION] }); @@ -91,7 +91,7 @@ function readYAMLConfigFile(filePath: SplitIO.MockedFeaturesFilePath): false | R yamldoc = yaml.safeLoad(data); } catch (e) { - log.error(e); + log.e(e); return {}; } @@ -101,7 +101,7 @@ function readYAMLConfigFile(filePath: SplitIO.MockedFeaturesFilePath): false | R const splitName = Object.keys(splitEntry)[0]; if (!splitName || !isString(splitEntry[splitName].treatment)) - log.error('Ignoring entry on YAML since the format is incorrect.'); + log.e('Ignoring entry on YAML since the format is incorrect.'); const mockData = splitEntry[splitName]; @@ -166,7 +166,7 @@ export default function splitsParserFromFile(settings: { features?: SplitIO.Mock // If we have a filePath, it means the extension is correct, choose the parser. if (endsWith(filePath, '.split')) { - log.warn('.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'); + log.w('.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'); mockData = readSplitConfigFile(filePath); } else { mockData = readYAMLConfigFile(filePath); diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index dbad6f4e..d5a1f813 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -28,12 +28,12 @@ export function fromObjectUpdaterFactory( splitsMock = splitsParser(settings); } catch (err) { loadError = err; - log.error(`There was an issue loading the mock Splits data, no changes will be applied to the current cache. ${err}`); + log.e(`There was an issue loading the mock Splits data, no changes will be applied to the current cache. ${err}`); } if (!loadError && splitsMock) { - log.debug('Splits data: '); - log.debug(JSON.stringify(splitsMock)); + log.d('Splits data: '); + log.d(JSON.stringify(splitsMock)); forOwn(splitsMock, function (val, name) { splits.push([ diff --git a/src/sync/polling/pollingManagerCS.ts b/src/sync/polling/pollingManagerCS.ts index 4c58763a..00b8be67 100644 --- a/src/sync/polling/pollingManagerCS.ts +++ b/src/sync/polling/pollingManagerCS.ts @@ -46,7 +46,7 @@ export default function pollingManagerCSFactory( if (!splitsSyncTask.isRunning()) return; // noop if not doing polling const splitsHaveSegments = storage.splits.usesSegments(); if (splitsHaveSegments !== mySegmentsSyncTask.isRunning()) { - log.info(`Turning segments data polling ${splitsHaveSegments ? 'ON' : 'OFF'}.`); + log.i(`Turning segments data polling ${splitsHaveSegments ? 'ON' : 'OFF'}.`); if (splitsHaveSegments) { startMySegmentsSyncTasks(); } else { @@ -75,7 +75,7 @@ export default function pollingManagerCSFactory( // Start periodic fetching (polling) start() { - log.info('Starting polling'); + log.i('Starting polling'); splitsSyncTask.start(); if (storage.splits.usesSegments()) startMySegmentsSyncTasks(); @@ -83,7 +83,7 @@ export default function pollingManagerCSFactory( // Stop periodic fetching (polling) stop() { - log.info('Stopping polling'); + log.i('Stopping polling'); if (splitsSyncTask.isRunning()) splitsSyncTask.stop(); stopMySegmentsSyncTasks(); diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index 6284b115..ca30fe66 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -28,9 +28,9 @@ export default function pollingManagerSSFactory( // Start periodic fetching (polling) start() { - log.info('Starting polling'); - log.debug(`Splits will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`); - log.debug(`Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`); + log.i('Starting polling'); + log.d(`Splits will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`); + log.d(`Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`); const startingUp = splitsSyncTask.start(); if (thenable(startingUp)) { @@ -42,7 +42,7 @@ export default function pollingManagerSSFactory( // Stop periodic fetching (polling) stop() { - log.info('Stopping polling'); + log.i('Stopping polling'); if (splitsSyncTask.isRunning()) splitsSyncTask.stop(); if (segmentsSyncTask.isRunning()) segmentsSyncTask.stop(); diff --git a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts index 7ff84ff5..db76608d 100644 --- a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts @@ -73,7 +73,7 @@ function mySegmentsUpdaterFactory( if (startingUp && retriesOnFailureBeforeReady > retry) { retry += 1; - log.warn(`Retrying download of segments #${retry}. Reason: ${error}`); + log.w(`Retrying download of segments #${retry}. Reason: ${error}`); return _mySegmentsUpdater(retry); } else { startingUp = false; diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index e0bb00f5..b1eb09f6 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -44,7 +44,7 @@ function segmentChangesUpdaterFactory( * @param {string[] | undefined} segmentNames list of segment names to fetch. By passing `undefined` it fetches the list of segments registered at the storage */ return function segmentChangesUpdater(segmentNames?: string[]) { - log.debug('Started segments update'); + log.d('Started segments update'); // If not a segment name provided, read list of available segments names to be updated. if (!segmentNames) segmentNames = segmentsCache.getRegisteredSegments(); @@ -56,7 +56,7 @@ function segmentChangesUpdaterFactory( const segmentName = segmentNames[index]; const since = segmentsCache.getChangeNumber(segmentName); - log.debug(`Processing segment ${segmentName}`); + log.d(`Processing segment ${segmentName}`); updaters.push(segmentChangesFetcher(since, segmentName, _promiseDecorator).then(function (changes) { let changeNumber = -1; @@ -68,7 +68,7 @@ function segmentChangesUpdaterFactory( changeNumber = x.till; } - log.debug(`Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`); + log.d(`Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`); }); return changeNumber; @@ -92,7 +92,7 @@ function segmentChangesUpdaterFactory( if (error.statusCode === 403) { // @TODO although factory status is destroyed, synchronization is not stopped readiness.destroy(); - inputValidationLog.error('Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'); + inputValidationLog.e('Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'); } return false; diff --git a/src/sync/polling/syncTasks/splitsSyncTask.ts b/src/sync/polling/syncTasks/splitsSyncTask.ts index 79e58c42..5ae62252 100644 --- a/src/sync/polling/syncTasks/splitsSyncTask.ts +++ b/src/sync/polling/syncTasks/splitsSyncTask.ts @@ -101,7 +101,7 @@ export function splitChangesUpdaterFactory( * @param {number} retry current number of retry attemps */ function _splitChangesUpdater(since: number, retry = 0): Promise { - log.debug(`Spin up split update using since = ${since}`); + log.d(`Spin up split update using since = ${since}`); const fetcherPromise = splitChangesFetcher(since, _promiseDecorator) .then((splitChanges: ISplitChangesResponse) => { @@ -109,9 +109,9 @@ export function splitChangesUpdaterFactory( const mutation = computeSplitsMutation(splitChanges.splits); - log.debug(`New splits ${mutation.added.length}`); - log.debug(`Removed splits ${mutation.removed.length}`); - log.debug(`Segment names collected ${mutation.segments.length}`); + log.d(`New splits ${mutation.added.length}`); + log.d(`Removed splits ${mutation.removed.length}`); + log.d(`Segment names collected ${mutation.segments.length}`); // Write into storage // @TODO if allowing custom storages, wrap errors as SplitErrors to distinguish from user callback errors @@ -136,11 +136,11 @@ export function splitChangesUpdaterFactory( startingUp = false; // Stop retrying. } - log.warn(`Error while doing fetch of Splits. ${error}`); + log.w(`Error while doing fetch of Splits. ${error}`); if (startingUp && retriesOnFailureBeforeReady && retriesOnFailureBeforeReady > retry) { retry += 1; - log.info(`Retrying download of splits #${retry}. Reason: ${error}`); + log.i(`Retrying download of splits #${retry}. Reason: ${error}`); return _splitChangesUpdater(since, retry); } else { startingUp = false; diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index cba39aed..49d20c1a 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -27,7 +27,7 @@ export default function SSEHandlerFactory(pushEmitter: IPushEventEmitter): ISseE try { errorWithParsedData = errorParser(error); } catch (err) { - log.warn(`Error parsing SSE error notification: ${err}`); + log.w(`Error parsing SSE error notification: ${err}`); } pushEmitter.emit(SSE_ERROR, errorWithParsedData); @@ -39,12 +39,12 @@ export default function SSEHandlerFactory(pushEmitter: IPushEventEmitter): ISseE try { messageWithParsedData = messageParser(message); } catch (err) { - log.warn(`Error parsing new SSE message notification: ${err}`); + log.w(`Error parsing new SSE message notification: ${err}`); return; } const { parsedData, data, channel, timestamp } = messageWithParsedData; - log.debug(`New SSE message received, with data: ${data}.`); + log.d(`New SSE message received, with data: ${data}.`); // we only handle update events if streaming is up. if (!notificationKeeper.isStreamingUp() && parsedData.type !== OCCUPANCY && parsedData.type !== CONTROL) diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index ff2243a5..c7203b41 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -40,7 +40,7 @@ export default function pushManagerFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(e + 'Falling back to polling mode.'); + log.w(e + 'Falling back to polling mode.'); return; } const authenticate = authenticateFactory(fetchAuth); @@ -89,14 +89,14 @@ export default function pushManagerFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.i(`Refreshing streaming token in ${delayInSeconds} seconds.`); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info('Connecting to push streaming.'); + log.i('Connecting to push streaming.'); const userKeys = userKey ? Object.keys(workers) : undefined; authenticate(userKeys).then( @@ -109,7 +109,7 @@ export default function pushManagerFactory( // emit PUSH_DISCONNECT if org is not whitelisted if (!authData.pushEnabled) { - log.info('Streaming is not available. Switching to polling mode.'); + log.i('Streaming is not available. Switching to polling mode.'); pushEmitter.emit(PUSH_DISCONNECT); // there is no need to close sseClient (it is not open on this scenario) return; } @@ -133,13 +133,13 @@ export default function pushManagerFactory( // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { - log.error(errorMessage); + log.e(errorMessage); return; } // Handle other HTTP and network errors const delayInMillis = reauthBackoff.scheduleCall(); - log.error(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); + log.e(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); } ); } @@ -147,7 +147,7 @@ export default function pushManagerFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info('Disconnecting from push streaming.'); + log.i('Disconnecting from push streaming.'); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -186,7 +186,7 @@ export default function pushManagerFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.error(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index 23fa813f..bbb6040f 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -38,7 +38,7 @@ export default function pushManagerCSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(e + 'Falling back to polling mode.'); + log.w(e + 'Falling back to polling mode.'); return; } const authenticate = authenticateFactory(fetchAuth); @@ -85,14 +85,14 @@ export default function pushManagerCSFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.i(`Refreshing streaming token in ${delayInSeconds} seconds.`); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info('Connecting to push streaming.'); + log.i('Connecting to push streaming.'); const userKeys = Object.keys(workers); // [Only for client-side] authenticate(userKeys).then( @@ -105,7 +105,7 @@ export default function pushManagerCSFactory( // emit PUSH_DISCONNECT if org is not whitelisted if (!authData.pushEnabled) { - log.info('Streaming is not available. Switching to polling mode.'); + log.i('Streaming is not available. Switching to polling mode.'); pushEmitter.emit(PUSH_DISCONNECT); // there is no need to close sseClient (it is not open on this scenario) return; } @@ -129,13 +129,13 @@ export default function pushManagerCSFactory( // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { - log.error(errorMessage); + log.e(errorMessage); return; } // Handle other HTTP and network errors const delayInMillis = reauthBackoff.scheduleCall(); - log.error(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); + log.e(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); } ); } @@ -143,7 +143,7 @@ export default function pushManagerCSFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info('Disconnecting from push streaming.'); + log.i('Disconnecting from push streaming.'); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -181,7 +181,7 @@ export default function pushManagerCSFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.error(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index fbbdb3f7..324f3cde 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -34,7 +34,7 @@ export default function pushManagerSSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(e + 'Falling back to polling mode.'); + log.w(e + 'Falling back to polling mode.'); return; } const authenticate = authenticateFactory(fetchAuth); @@ -66,14 +66,14 @@ export default function pushManagerSSFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.i(`Refreshing streaming token in ${delayInSeconds} seconds.`); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info('Connecting to push streaming.'); + log.i('Connecting to push streaming.'); authenticate().then( function (authData) { @@ -85,7 +85,7 @@ export default function pushManagerSSFactory( // emit PUSH_DISCONNECT if org is not whitelisted if (!authData.pushEnabled) { - log.info('Streaming is not available. Switching to polling mode.'); + log.i('Streaming is not available. Switching to polling mode.'); pushEmitter.emit(PUSH_DISCONNECT); // there is no need to close sseClient (it is not open on this scenario) return; } @@ -106,13 +106,13 @@ export default function pushManagerSSFactory( // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { - log.error(errorMessage); + log.e(errorMessage); return; } // Handle other HTTP and network errors const delayInMillis = reauthBackoff.scheduleCall(); - log.error(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); + log.e(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); } ); } @@ -120,7 +120,7 @@ export default function pushManagerSSFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info('Disconnecting from push streaming.'); + log.i('Disconnecting from push streaming.'); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -158,7 +158,7 @@ export default function pushManagerSSFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.error(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/sync/submitters/eventsSyncTask.ts b/src/sync/submitters/eventsSyncTask.ts index cb68cf39..19c7fe85 100644 --- a/src/sync/submitters/eventsSyncTask.ts +++ b/src/sync/submitters/eventsSyncTask.ts @@ -35,7 +35,7 @@ export function eventsSyncTaskFactory( // register eventsSubmitter to be executed when events cache is full eventsCache.setOnFullQueueCb(() => { - log.info('Flushing full events queue and reseting timer.'); + log.i('Flushing full events queue and reseting timer.'); syncTask.execute(); }); diff --git a/src/sync/submitters/submitterSyncTask.ts b/src/sync/submitters/submitterSyncTask.ts index f2d4a854..4a5acbcc 100644 --- a/src/sync/submitters/submitterSyncTask.ts +++ b/src/sync/submitters/submitterSyncTask.ts @@ -25,7 +25,7 @@ export function submitterSyncTaskFactory( const data = sourceCache.state(); const dataCount: number | '' = typeof data.length === 'number' ? data.length : ''; - log.info(`Pushing ${dataCount} ${dataName}.`); + log.i(`Pushing ${dataCount} ${dataName}.`); const latencyTrackerStop = latencyTracker && latencyTracker.start(); const jsonPayload = JSON.stringify(fromCacheToPayload ? fromCacheToPayload(data) : data); @@ -36,14 +36,14 @@ export function submitterSyncTaskFactory( sourceCache.clear(); // we clear the queue if request successes. }).catch(err => { if (!maxRetries) { - log.warn(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); + log.w(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); } else if (retries === maxRetries) { retries = 0; sourceCache.clear(); // we clear the queue if request fails after retries. - log.warn(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); + log.w(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); } else { retries++; - log.warn(`Failed to push ${dataCount} ${dataName}, keeping data to retry on next iteration. Reason ${err}.`); + log.w(`Failed to push ${dataCount} ${dataName}, keeping data to retry on next iteration. Reason ${err}.`); } }); diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index 01799bbb..3b32e515 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -58,15 +58,15 @@ export function syncManagerOnlineFactory( function startPolling() { if (!pollingManager.isRunning()) { - log.info('Streaming not available. Starting periodic fetch of data.'); + log.i('Streaming not available. Starting periodic fetch of data.'); pollingManager.start(); } else { - log.info('Streaming couldn\'t connect. Continue periodic fetch of data.'); + log.i('Streaming couldn\'t connect. Continue periodic fetch of data.'); } } function stopPollingAndSyncAll() { - log.info('PUSH (re)connected. Syncing and stopping periodic fetch of data.'); + log.i('PUSH (re)connected. Syncing and stopping periodic fetch of data.'); // if polling, stop if (pollingManager.isRunning()) pollingManager.stop(); diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index 530fc9b5..3487dd69 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -16,7 +16,7 @@ export default function syncTaskFactory(task: (...a function execute(...args: Input) { executing = true; - log.debug(`Running ${taskName}`); + log.d(`Running ${taskName}`); return task(...args).then(result => { executing = false; if (running) timeoutID = setTimeout(execute, period, ...args); @@ -34,7 +34,7 @@ export default function syncTaskFactory(task: (...a start(...args: Input) { if (!running) { running = true; - log.debug(`Starting ${taskName}. Running each ${period} millis`); + log.d(`Starting ${taskName}. Running each ${period} millis`); return execute(...args); } }, @@ -42,7 +42,7 @@ export default function syncTaskFactory(task: (...a stop() { running = false; if (timeoutID) { - log.debug(`Stopping ${taskName}`); + log.d(`Stopping ${taskName}`); clearTimeout(timeoutID); timeoutID = undefined; } diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index 081bef70..d49514b2 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -23,7 +23,7 @@ export default function eventTrackerFactory( const msg = `event of type "${eventTypeId}" for traffic type "${trafficTypeName}". Key: ${key}. Value: ${value}. Timestamp: ${timestamp}. ${properties ? 'With properties.' : 'With no properties.'}`; if (tracked) { - log.info(`Successfully qeued ${msg}`); + log.i(`Successfully qeued ${msg}`); if (integrationsManager) { // Wrap in a timeout because we don't want it to be blocking. setTimeout(function () { @@ -35,7 +35,7 @@ export default function eventTrackerFactory( }, 0); } } else { - log.warn(`Failed to queue ${msg}`); + log.w(`Failed to queue ${msg}`); } return tracked; diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index aa9bf94f..a35694cc 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -62,9 +62,9 @@ export default function impressionsTrackerFactory( // If we're on an async storage, handle error and log it. if (thenable(res)) { res.then(() => { - log.debug(`Successfully stored ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}.`); + log.d(`Successfully stored ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}.`); }).catch(err => { - log.error(`Could not store impressions bulk with ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}. Error: ${err}`); + log.e(`Could not store impressions bulk with ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}. Error: ${err}`); }); } @@ -88,7 +88,7 @@ export default function impressionsTrackerFactory( try { // An exception on the listeners should not break the SDK. if (impressionListener) impressionListener.logImpression(impressionData); } catch (err) { - log.error(`Impression listener logImpression method threw: ${err}.`); + log.e(`Impression listener logImpression method threw: ${err}.`); } }, 0); } diff --git a/src/utils/inputValidation/__tests__/apiKey.spec.ts b/src/utils/inputValidation/__tests__/apiKey.spec.ts index 1fd8aa76..8ebceaba 100644 --- a/src/utils/inputValidation/__tests__/apiKey.spec.ts +++ b/src/utils/inputValidation/__tests__/apiKey.spec.ts @@ -29,7 +29,7 @@ describe('validateApiKey', () => { const validApiKey = 'qjok3snti4dgsticade5hfphmlucarsflv14'; expect(validateApiKey(validApiKey)).toBe(validApiKey); // It should return the passed string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. mockClear(); }); @@ -40,9 +40,9 @@ describe('validateApiKey', () => { const expectedLog = invalidKeys[i]['msg']; expect(validateApiKey(invalidApiKey)).toBe(false); // Invalid strings should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(expectedLog); // The error should be logged for the invalid string. + expect(loggerMock.e.mock.calls[0][0]).toEqual(expectedLog); // The error should be logged for the invalid string. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } mockClear(); @@ -57,13 +57,13 @@ describe('validateAndTrackApiKey', () => { const validApiKey3 = '84ynbsnti4dgsticade5hfphmlucars92uih'; expect(validateAndTrackApiKey(validApiKey1)).toBe(validApiKey1); - expect(loggerMock.warn.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. + expect(loggerMock.w.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. expect(validateAndTrackApiKey(validApiKey2)).toBe(validApiKey2); - expect(loggerMock.warn.mock.calls).toEqual([['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a new api key, we get a warning. + expect(loggerMock.w.mock.calls).toEqual([['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a new api key, we get a warning. expect(validateAndTrackApiKey(validApiKey3)).toBe(validApiKey3); - expect(loggerMock.warn.mock.calls[0]).toEqual(['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']); // We register a new api key, we get a warning. + expect(loggerMock.w.mock.calls[0]).toEqual(['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']); // We register a new api key, we get a warning. // We will release the used keys and expect no warnings next time. releaseApiKey(validApiKey1); @@ -73,7 +73,7 @@ describe('validateAndTrackApiKey', () => { mockClear(); expect(validateAndTrackApiKey(validApiKey1)).toBe(validApiKey1); - expect(loggerMock.warn.mock.calls.length).toBe(0); // If all the keys were released and we try again, there is no warning. + expect(loggerMock.w.mock.calls.length).toBe(0); // If all the keys were released and we try again, there is no warning. releaseApiKey(validApiKey1); // clean up the cache of api keys for next test mockClear(); @@ -83,7 +83,7 @@ describe('validateAndTrackApiKey', () => { const validApiKey = '84ynbsnti4dgsticade5hfphmlucars92uih'; expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); - expect(loggerMock.warn.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. + expect(loggerMock.w.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); @@ -93,7 +93,7 @@ describe('validateAndTrackApiKey', () => { // Same key one more time, 3 instances plus new one. expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); - expect(loggerMock.warn.mock.calls).toEqual([ + expect(loggerMock.w.mock.calls).toEqual([ ['Factory instantiation: You already have 1 factory with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'], // We register a the same api key again, we get a warning with the number of instances we have. ['Factory instantiation: You already have 2 factories with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'], // We register a the same api key again, we get a warning with the number of instances we have. ['Factory instantiation: You already have 3 factories with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'] // We register a the same api key again, we get a warning with the number of instances we have. @@ -108,7 +108,7 @@ describe('validateAndTrackApiKey', () => { // So we get the warning again. expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); - expect(loggerMock.warn.mock.calls).toEqual([['Factory instantiation: You already have 1 factory with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a the same api key again, we get a warning with the number of instances we have. + expect(loggerMock.w.mock.calls).toEqual([['Factory instantiation: You already have 1 factory with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a the same api key again, we get a warning with the number of instances we have. // Leave it with 0 releaseApiKey(validApiKey); @@ -117,7 +117,7 @@ describe('validateAndTrackApiKey', () => { mockClear(); expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); - expect(loggerMock.warn.mock.calls.length).toBe(0); // s users, there is no warning when we use it again. + expect(loggerMock.w.mock.calls.length).toBe(0); // s users, there is no warning when we use it again. releaseApiKey(validApiKey); // clean up the cache just in case a new test is added mockClear(); diff --git a/src/utils/inputValidation/__tests__/attributes.spec.ts b/src/utils/inputValidation/__tests__/attributes.spec.ts index 6331c325..4c395dc2 100644 --- a/src/utils/inputValidation/__tests__/attributes.spec.ts +++ b/src/utils/inputValidation/__tests__/attributes.spec.ts @@ -22,8 +22,8 @@ describe('INPUT VALIDATION for Attributes', () => { const validAttributes = { amIvalid: 'yes', 'are_you_sure': true, howMuch: 10 }; expect(validateAttributes(validAttributes, 'some_method_attrs')).toEqual(validAttributes); // It should return the passed map if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear; }); @@ -31,8 +31,8 @@ describe('INPUT VALIDATION for Attributes', () => { test('Should return the passed value if it is null or undefined (since attributes are optional) without logging any errors', () => { expect(validateAttributes(null, 'some_method_attrs')).toBe(null); // It should return the passed null. expect(validateAttributes(undefined, 'some_method_attrs')).toBe(undefined); // It should return the passed undefined. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -42,12 +42,12 @@ describe('INPUT VALIDATION for Attributes', () => { const invalidAttribute = invalidAttributes[i]; expect(validateAttributes(invalidAttribute, 'test_method')).toBe(false); // Invalid attribute objects should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual('test_method: attributes must be a plain object.'); // The error should be logged for the invalid attributes map. + expect(loggerMock.e.mock.calls[0][0]).toEqual('test_method: attributes must be a plain object.'); // The error should be logged for the invalid attributes map. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/event.spec.ts b/src/utils/inputValidation/__tests__/event.spec.ts index 1d8d2209..a5f1c4b2 100644 --- a/src/utils/inputValidation/__tests__/event.spec.ts +++ b/src/utils/inputValidation/__tests__/event.spec.ts @@ -36,13 +36,13 @@ describe('INPUT VALIDATION for Event types', () => { test('Should return the provided event type if it is a valid string without logging any errors', () => { expect(validateEvent('valid:Too', 'some_method_eventType')).toBe('valid:Too'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. expect(validateEvent('I.am.valid-string_ValUe', 'some_method_eventType')).toBe('I.am.valid-string_ValUe'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. expect(validateEvent('a', 'some_method_eventType')).toBe('a'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -53,12 +53,12 @@ describe('INPUT VALIDATION for Event types', () => { const expectedLog = invalidEvents[i]['msg'](invalidValue); expect(validateEvent(invalidValue, 'test_method')).toBe(false); // Invalid event types should always return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. + expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/eventProperties.spec.ts b/src/utils/inputValidation/__tests__/eventProperties.spec.ts index 057311ac..9749989a 100644 --- a/src/utils/inputValidation/__tests__/eventProperties.spec.ts +++ b/src/utils/inputValidation/__tests__/eventProperties.spec.ts @@ -46,8 +46,8 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return the passed null since it is valid with default event size.'); - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -59,12 +59,12 @@ describe('INPUT VALIDATION for Event Properties', () => { properties: false, size: 1024 }); // It should return default size and properties false if the properties value is not an object or null/undefined.'); - expect(loggerMock.error.mock.calls).toEqual([['some_method_eventProps: properties must be a plain object.']]); // Should log an error. - loggerMock.error.mockClear(); + expect(loggerMock.e.mock.calls).toEqual([['some_method_eventProps: properties must be a plain object.']]); // Should log an error. + loggerMock.e.mockClear(); }); - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -89,8 +89,8 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(validProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -121,11 +121,11 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(providedProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(4); // It should have logged one warning per each property of the invalid type. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(4); // It should have logged one warning per each property of the invalid type. ['willBeNulled1', 'willBeNulled2', 'willBeNulled3', 'willBeNulled4'].forEach((key, index) => { - expect(loggerMock.warn.mock.calls[index][0]).toBe(`some_method_eventProps: Property ${key} is of invalid type. Setting value to null.`); + expect(loggerMock.w.mock.calls[index][0]).toBe(`some_method_eventProps: Property ${key} is of invalid type. Setting value to null.`); }); mockClear(); @@ -145,8 +145,8 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return the properties and the event size.'); - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. // @ts-ignore validProperties.a = null; // Adding one prop to exceed the limit. @@ -158,8 +158,8 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return the properties and the event size.'); - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls).toEqual([['some_method_eventProps: Event has more than 300 properties. Some of them will be trimmed when processed.']]); // It should have logged a warning. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls).toEqual([['some_method_eventProps: Event has more than 300 properties. Some of them will be trimmed when processed.']]); // It should have logged a warning. mockClear(); }); @@ -182,8 +182,8 @@ describe('INPUT VALIDATION for Event Properties', () => { // It should return the properties and the event size.'); expect(validProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // Should not log any warnings. // @ts-ignore validProperties.a = null; // exceed by two bytes (1 char string key which is two bytes, null value which we count as 0 to match other SDKs) @@ -196,10 +196,10 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return false instead of the properties and the event size.'); - expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. - expect(loggerMock.error.mock.calls).toEqual([['some_method_eventProps: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.']]); // Should log an error. + expect(loggerMock.w.mock.calls.length).toBe(0); // Should not log any warnings. + expect(loggerMock.e.mock.calls).toEqual([['some_method_eventProps: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.']]); // Should log an error. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/eventValue.spec.ts b/src/utils/inputValidation/__tests__/eventValue.spec.ts index 042bba6e..c3f28dea 100644 --- a/src/utils/inputValidation/__tests__/eventValue.spec.ts +++ b/src/utils/inputValidation/__tests__/eventValue.spec.ts @@ -21,22 +21,22 @@ describe('INPUT VALIDATION for Event Values', () => { test('Should return the passed value if it is a valid finite number without logging any errors', () => { expect(validateEventValue(50, 'some_method_eventValue')).toBe(50); // It should return the passed number if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. expect(validateEventValue(-50, 'some_method_eventValue')).toBe(-50); // It should return the passed number if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); test('Should return the passed value if it is a null or undefined (since it is optional) without logging any errors', () => { expect(validateEventValue(null, 'some_method_eventValue')).toBe(null); // It should return the passed number if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. expect(validateEventValue(undefined, 'some_method_eventValue')).toBe(undefined); // It should return the passed number if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -46,12 +46,12 @@ describe('INPUT VALIDATION for Event Values', () => { const invalidValue = invalidValues[i]; expect(validateEventValue(invalidValue, 'test_method')).toBe(false); // Invalid event values should always return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual('test_method: value must be a finite number.'); // Should log the error for the invalid event value. + expect(loggerMock.e.mock.calls[0][0]).toEqual('test_method: value must be a finite number.'); // Should log the error for the invalid event value. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/isOperational.spec.ts b/src/utils/inputValidation/__tests__/isOperational.spec.ts index 60681862..fe44ebdd 100644 --- a/src/utils/inputValidation/__tests__/isOperational.spec.ts +++ b/src/utils/inputValidation/__tests__/isOperational.spec.ts @@ -10,8 +10,8 @@ describe('validateIfNotDestroyed', () => { // @ts-ignore expect(validateIfNotDestroyed(readinessManagerMock)).toBe(true); // It should return true if the client is operational (it is NOT destroyed). expect(readinessManagerMock.isDestroyed.mock.calls.length).toBe(1); // It checks for destroyed status using the context. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // Should not log any warnings. mockClear(); }); @@ -22,8 +22,8 @@ describe('validateIfNotDestroyed', () => { // @ts-ignore expect(validateIfNotDestroyed(readinessManagerMock)).toBe(false); // It should return false if the client is NOT operational (it is destroyed). expect(readinessManagerMock.isDestroyed.mock.calls.length).toBe(1); // It checks for destroyed status using the context. - expect(loggerMock.error.mock.calls).toEqual([['Client has already been destroyed - no calls possible.']]); // Should log an error. - expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. + expect(loggerMock.e.mock.calls).toEqual([['Client has already been destroyed - no calls possible.']]); // Should log an error. + expect(loggerMock.w.mock.calls.length).toBe(0); // But it should not log any warnings. mockClear(); }); @@ -37,8 +37,8 @@ describe('validateIfOperational', () => { // @ts-ignore expect(validateIfOperational(readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready. expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for readiness status using the context. - expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // But it should not log any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // But it should not log any errors. mockClear(); }); @@ -50,8 +50,8 @@ describe('validateIfOperational', () => { expect(validateIfOperational(readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready. expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for SDK_READY status. expect(readinessManagerMock.isReadyFromCache.mock.calls.length).toBe(1); // It checks for SDK_READY_FROM_CACHE status. - expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // But it should not log any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // But it should not log any errors. mockClear(); }); @@ -63,8 +63,8 @@ describe('validateIfOperational', () => { expect(validateIfOperational(readinessManagerMock, 'test_method')).toBe(false); // It should return true if SDK was ready. expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for SDK_READY status. expect(readinessManagerMock.isReadyFromCache.mock.calls.length).toBe(1); // It checks for SDK_READY_FROM_CACHE status. - expect(loggerMock.warn.mock.calls).toEqual([['test_method: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.']]); // It should log the expected warning. - expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. + expect(loggerMock.w.mock.calls).toEqual([['test_method: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.']]); // It should log the expected warning. + expect(loggerMock.e.mock.calls.length).toBe(0); // But it should not log any errors. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/key.spec.ts b/src/utils/inputValidation/__tests__/key.spec.ts index 1a91002e..9879f7ed 100644 --- a/src/utils/inputValidation/__tests__/key.spec.ts +++ b/src/utils/inputValidation/__tests__/key.spec.ts @@ -49,12 +49,12 @@ describe('INPUT VALIDATION for Key', () => { }; expect(validateKey(validKey, 'some_method_keys')).toEqual(validKey); // It will return the valid key. - expect(loggerMock.error.mock.calls.length).toBe(0); // No errors should be logged. + expect(loggerMock.e.mock.calls.length).toBe(0); // No errors should be logged. expect(validateKey(validObjKey, 'some_method_keys')).toEqual(validObjKey); // It will return the valid key. - expect(loggerMock.error.mock.calls.length).toBe(0); // No errors should be logged. + expect(loggerMock.e.mock.calls.length).toBe(0); // No errors should be logged. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -65,12 +65,12 @@ describe('INPUT VALIDATION for Key', () => { const expectedLog = invalidKeys[i]['msg']('key'); expect(validateKey(invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -81,12 +81,12 @@ describe('INPUT VALIDATION for Key', () => { const expectedLog = stringifyableKeys[i]['msg']('key', invalidKey); validateKey(invalidKey, 'test_method'); - expect(loggerMock.warn.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // But if the logger allows for warnings, it should be logged. + expect(loggerMock.w.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // But if the logger allows for warnings, it should be logged. - loggerMock.warn.mockClear(); + loggerMock.w.mockClear(); } - expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // It should have not logged any errors. mockClear(); }); @@ -95,12 +95,12 @@ describe('INPUT VALIDATION for Key', () => { // Test invalid object format for (let i = 0; i < invalidKeyObjects.length; i++) { expect(validateKey(invalidKeyObjects[i], 'test_method')).toBe(false); // Invalid key objects should return false. - expect(loggerMock.error.mock.calls[loggerMock.error.mock.calls.length - 1][0]).toEqual(`test_method: ${errorMsgs.WRONG_KEY_PROPS}`); // The error should be logged for the invalid key. + expect(loggerMock.e.mock.calls[loggerMock.e.mock.calls.length - 1][0]).toEqual(`test_method: ${errorMsgs.WRONG_KEY_PROPS}`); // The error should be logged for the invalid key. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); // Test invalid matchingKey @@ -112,12 +112,12 @@ describe('INPUT VALIDATION for Key', () => { const expectedLog = invalidKeys[i]['msg']('matchingKey'); expect(validateKey(invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); @@ -130,12 +130,12 @@ describe('INPUT VALIDATION for Key', () => { const expectedLog = invalidKeys[i]['msg']('bucketingKey'); expect(validateKey(invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); @@ -148,10 +148,10 @@ describe('INPUT VALIDATION for Key', () => { let expectedLogBK = invalidKeys[1]['msg']('bucketingKey'); expect(validateKey(invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The error should be logged for the invalid key property. - expect(loggerMock.error.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The error should be logged for the invalid key property. + expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The error should be logged for the invalid key property. + expect(loggerMock.e.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The error should be logged for the invalid key property. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -169,10 +169,10 @@ describe('INPUT VALIDATION for Key', () => { let expectedLogBK = stringifyableKeys[1]['msg']('bucketingKey', invalidKey.bucketingKey); expect(validateKey(invalidKey, 'test_method')).toEqual(expectedKey); // If a key object had stringifyable values, those will be stringified and Key returned. - expect(loggerMock.warn.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The warning should be logged for the stringified prop if warnings are enabled. - expect(loggerMock.warn.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The warning should be logged for the stringified prop if warnings are enabled. + expect(loggerMock.w.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The warning should be logged for the stringified prop if warnings are enabled. + expect(loggerMock.w.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The warning should be logged for the stringified prop if warnings are enabled. - expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // It should have not logged any errors. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/preloadedData.spec.ts b/src/utils/inputValidation/__tests__/preloadedData.spec.ts index 29f3a8a6..4dd26568 100644 --- a/src/utils/inputValidation/__tests__/preloadedData.spec.ts +++ b/src/utils/inputValidation/__tests__/preloadedData.spec.ts @@ -141,17 +141,17 @@ test('INPUT VALIDATION for preloadedData', () => { expect(validatePreloadedData(testCase.input, method)).toBe(testCase.output); if (testCase.error) { - expect(loggerMock.error.mock.calls[0]).toEqual([testCase.error]); // Should log the error for the invalid preloadedData. - loggerMock.error.mockClear(); + expect(loggerMock.e.mock.calls[0]).toEqual([testCase.error]); // Should log the error for the invalid preloadedData. + loggerMock.e.mockClear(); } else { - expect(loggerMock.error.mock.calls.length === 0).toBe(true); // Should not log any error. + expect(loggerMock.e.mock.calls.length === 0).toBe(true); // Should not log any error. } if (testCase.warn) { - expect(loggerMock.warn.mock.calls[0]).toEqual([testCase.warn]); // Should log the warning for the given preloadedData. - loggerMock.warn.mockClear(); + expect(loggerMock.w.mock.calls[0]).toEqual([testCase.warn]); // Should log the warning for the given preloadedData. + loggerMock.w.mockClear(); } else { - expect(loggerMock.warn.mock.calls.length === 0).toBe(true); // Should not log any warning. + expect(loggerMock.w.mock.calls.length === 0).toBe(true); // Should not log any warning. } } }); diff --git a/src/utils/inputValidation/__tests__/split.spec.ts b/src/utils/inputValidation/__tests__/split.spec.ts index 53fa76c0..cffb37cb 100644 --- a/src/utils/inputValidation/__tests__/split.spec.ts +++ b/src/utils/inputValidation/__tests__/split.spec.ts @@ -37,13 +37,13 @@ describe('INPUT VALIDATION for Split name', () => { test('Should return the provided split name if it is a valid string without logging any errors', () => { expect(validateSplit('splitName', 'some_method_splitName')).toBe('splitName'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. + expect(loggerMock.e.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. expect(validateSplit('split_name', 'some_method_splitName')).toBe('split_name'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. + expect(loggerMock.e.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. expect(validateSplit('A_split-name_29', 'some_method_splitName')).toBe('A_split-name_29'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. + expect(loggerMock.e.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -52,12 +52,12 @@ describe('INPUT VALIDATION for Split name', () => { for (let i = 0; i < trimmableSplits.length; i++) { const trimmableSplit = trimmableSplits[i]; expect(validateSplit(trimmableSplit, 'some_method_splitName')).toBe(trimmableSplit.trim()); // It should return the trimmed version of the split name received. - expect(loggerMock.warn.mock.calls[0][0]).toEqual(`some_method_splitName: ${errorMsgs.TRIMMABLE_SPLIT(trimmableSplit)}`); // Should log a warning if those are enabled. + expect(loggerMock.w.mock.calls[0][0]).toEqual(`some_method_splitName: ${errorMsgs.TRIMMABLE_SPLIT(trimmableSplit)}`); // Should log a warning if those are enabled. - loggerMock.warn.mockClear(); + loggerMock.w.mockClear(); } - expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // It should have not logged any errors. mockClear(); }); @@ -69,12 +69,12 @@ describe('INPUT VALIDATION for Split name', () => { const expectedLog = invalidSplits[i]['msg'](invalidValue); expect(validateSplit(invalidValue, 'test_method')).toBe(false); // Invalid event types should always return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. + expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/splitExistance.spec.ts b/src/utils/inputValidation/__tests__/splitExistance.spec.ts index 3f6a3c1a..642c651e 100644 --- a/src/utils/inputValidation/__tests__/splitExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/splitExistance.spec.ts @@ -24,8 +24,8 @@ describe('Split existance (special case)', () => { expect(validateSplitExistance(readinessManagerMock, 'some_split', 'a label', 'test_method')).toBe(true); // Should always return true when the SDK is not ready. expect(validateSplitExistance(readinessManagerMock, 'some_split', LabelConstants.SPLIT_NOT_FOUND, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. - expect(loggerMock.warn.mock.calls.length).toBe(0); // There should have been no warning logs since the SDK was not ready yet. - expect(loggerMock.error.mock.calls.length).toBe(0); // There should have been no error logs since the SDK was not ready yet. + expect(loggerMock.w.mock.calls.length).toBe(0); // There should have been no warning logs since the SDK was not ready yet. + expect(loggerMock.e.mock.calls.length).toBe(0); // There should have been no error logs since the SDK was not ready yet. // Prepare the mock to fake that the SDK is ready now. (readinessManagerMock.isReady as jest.Mock).mockImplementation(() => true); @@ -33,17 +33,17 @@ describe('Split existance (special case)', () => { expect(validateSplitExistance(readinessManagerMock, 'other_split', {}, 'other_method')).toBe(true); // Should return true if it receives a Split Object instead of null (when the object is not found, for manager). expect(validateSplitExistance(readinessManagerMock, 'other_split', 'a label', 'other_method')).toBe(true); // Should return true if it receives a Label and it is not split not found (when the Split was not found on the storage, for client). - expect(loggerMock.warn.mock.calls.length).toBe(0); // There should have been no warning logs since the values we used so far were considered valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // There should have been no error logs since the values we used so far were considered valid. + expect(loggerMock.w.mock.calls.length).toBe(0); // There should have been no warning logs since the values we used so far were considered valid. + expect(loggerMock.e.mock.calls.length).toBe(0); // There should have been no error logs since the values we used so far were considered valid. expect(validateSplitExistance(readinessManagerMock, 'other_split', null, 'other_method')).toBe(false); // Should return false if it receives a non-truthy value as a split object or label expect(validateSplitExistance(readinessManagerMock, 'other_split', undefined, 'other_method')).toBe(false); // Should return false if it receives a non-truthy value as a split object or label expect(validateSplitExistance(readinessManagerMock, 'other_split', LabelConstants.SPLIT_NOT_FOUND, 'other_method')).toBe(false); // Should return false if it receives a label but it is the split not found one. - expect(loggerMock.warn.mock.calls.length).toBe(3); // It should have logged 3 warnings, one per each time we called it - loggerMock.warn.mock.calls.forEach(call => expect(call[0]).toBe(`other_method: ${errorMsgs.NOT_EXISTENT_SPLIT('other_split')}`)); // Warning logs should have the correct message. + expect(loggerMock.w.mock.calls.length).toBe(3); // It should have logged 3 warnings, one per each time we called it + loggerMock.w.mock.calls.forEach(call => expect(call[0]).toBe(`other_method: ${errorMsgs.NOT_EXISTENT_SPLIT('other_split')}`)); // Warning logs should have the correct message. - expect(loggerMock.error.mock.calls.length).toBe(0); // We log warnings, not errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // We log warnings, not errors. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/splits.spec.ts b/src/utils/inputValidation/__tests__/splits.spec.ts index 1c7a717f..8e8df37b 100644 --- a/src/utils/inputValidation/__tests__/splits.spec.ts +++ b/src/utils/inputValidation/__tests__/splits.spec.ts @@ -43,9 +43,9 @@ describe('INPUT VALIDATION for Split names', () => { expect(validateSplits(validArr, 'some_method_splits')).toEqual(validArr); // It should return the provided array without changes if it is valid. expect(validateSplitMock.mock.calls.length).toBe(validArr.length); // Should have validated each value independently. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors on the collection. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors on the collection. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. }); test('Should return the provided array if it is a valid splits names array removing duplications, without logging any errors', () => { @@ -53,21 +53,21 @@ describe('INPUT VALIDATION for Split names', () => { expect(validateSplits(validArr, 'some_method_splits')).toEqual(uniq(validArr)); // It should return the provided array without changes if it is valid. expect(validateSplitMock.mock.calls.length).toBe(validArr.length); // Should have validated each value independently. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors on the collection. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors on the collection. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. }); test('Should return false and log an error for the array if it is invalid', () => { for (let i = 0; i < invalidSplits.length; i++) { expect(validateSplits(invalidSplits[i], 'test_method')).toBe(false); // It will return false as the array is of an incorrect type. - expect(loggerMock.error.mock.calls).toEqual([['test_method: split_names must be a non-empty array.']]); // Should log the error for the collection. + expect(loggerMock.e.mock.calls).toEqual([['test_method: split_names must be a non-empty array.']]); // Should log the error for the collection. expect(validateSplitMock.mock.calls.length).toBe(0); // Should not try to validate any inner value if there is no valid array. - loggerMock.error.mockClear(); + loggerMock.e.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. }); test('Should strip out any invalid value from the array', () => { @@ -81,7 +81,7 @@ describe('INPUT VALIDATION for Split names', () => { expect(validateSplitMock.mock.calls[i]).toEqual([myArr[i], 'test_method', 'split name']); // Should validate any inner value independently. } - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any error for the collection. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings for the collection. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any error for the collection. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings for the collection. }); }); diff --git a/src/utils/inputValidation/__tests__/trafficType.spec.ts b/src/utils/inputValidation/__tests__/trafficType.spec.ts index d7ab1e2b..1b7a8517 100644 --- a/src/utils/inputValidation/__tests__/trafficType.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficType.spec.ts @@ -37,13 +37,13 @@ describe('INPUT VALIDATION for Traffic Types', () => { test('Should return the provided traffic type if it is a valid string without logging any errors', () => { expect(validateTrafficType('traffictype', 'some_method_trafficType')).toBe('traffictype'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. expect(validateTrafficType('traffic_type', 'some_method_trafficType')).toBe('traffic_type'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. expect(validateTrafficType('traffic-type-23', 'some_method_trafficType')).toBe('traffic-type-23'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -53,10 +53,10 @@ describe('INPUT VALIDATION for Traffic Types', () => { const convertibleTrafficType = convertibleTrafficTypes[i]; expect(validateTrafficType(convertibleTrafficType, 'some_method_trafficType')).toBe(convertibleTrafficType.toLowerCase()); // It should return the lowercase version of the traffic type received. - expect(loggerMock.warn.mock.calls[i][0]).toEqual(`some_method_trafficType: ${errorMsgs.LOWERCASE_TRAFFIC_TYPE}`); // Should log a warning. + expect(loggerMock.w.mock.calls[i][0]).toEqual(`some_method_trafficType: ${errorMsgs.LOWERCASE_TRAFFIC_TYPE}`); // Should log a warning. } - expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // It should have not logged any errors. mockClear(); }); @@ -67,10 +67,10 @@ describe('INPUT VALIDATION for Traffic Types', () => { const expectedLog = invalidTrafficTypes[i]['msg']; expect(validateTrafficType(invalidValue, 'test_method')).toBe(false); // Invalid traffic types should always return false. - expect(loggerMock.error.mock.calls[i][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid traffic type. + expect(loggerMock.e.mock.calls[i][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid traffic type. } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts b/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts index c1869f97..40ad0ee7 100644 --- a/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts @@ -39,15 +39,15 @@ describe('validateTrafficTypeExistance', () => { // Not ready and not localstorage expect(validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is not ready yet, it will return true. expect(splitsCacheMock.trafficTypeExists.mock.calls.length).toBe(0); // If the SDK is not ready yet, it does not try to go to the storage. - expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. - expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. + expect(loggerMock.e.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. // Ready and in localstorage mode. readinessManagerMock.isReady.mockImplementation(() => true); expect(validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, LOCALHOST_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is in localhost mode, it will return true. expect(splitsCacheMock.trafficTypeExists.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it does not try to go to the storage. - expect(loggerMock.warn.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any errors. mockClear(); }); @@ -58,8 +58,8 @@ describe('validateTrafficTypeExistance', () => { expect(validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_EXISTENT_TT, 'test_method')).toBe(true); // If the SDK is in condition to validate but the TT exists, it will return true. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_EXISTENT_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the storage. - expect(loggerMock.warn.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any errors. + expect(loggerMock.w.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any warnings. + expect(loggerMock.e.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any errors. mockClear(); splitsCacheMock.trafficTypeExists.mockClear(); @@ -69,8 +69,8 @@ describe('validateTrafficTypeExistance', () => { // Ready, standalone, and the TT not exists in the storage. expect(validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_NOT_EXISTENT_TT, 'test_method_y')).toBe(false); // If the SDK is in condition to validate but the TT does not exist in the storage, it will return false. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_NOT_EXISTENT_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the storage. - expect(loggerMock.warn.mock.calls).toEqual([[`test_method_y: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. - expect(loggerMock.error.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. + expect(loggerMock.w.mock.calls).toEqual([[`test_method_y: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. + expect(loggerMock.e.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. mockClear(); splitsCacheMock.trafficTypeExists.mockClear(); @@ -82,14 +82,14 @@ describe('validateTrafficTypeExistance', () => { const validationPromise = validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_EXISTENT_ASYNC_TT, 'test_method_z'); expect(thenable(validationPromise)).toBe(true); // If the storage is async, it should also return a promise. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_EXISTENT_ASYNC_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the async storage. - expect(loggerMock.warn.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. - expect(loggerMock.error.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.w.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.e.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. const isValid = await validationPromise; expect(isValid).toBe(true); // As the split existed, it will resolve to true. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It was valid so no logs. - expect(loggerMock.error.mock.calls.length).toBe(0); // It was valid so no logs. + expect(loggerMock.w.mock.calls.length).toBe(0); // It was valid so no logs. + expect(loggerMock.e.mock.calls.length).toBe(0); // It was valid so no logs. // Second round, a TT that does not exist on the asnyc storage splitsCacheMock.trafficTypeExists.mockClear(); @@ -97,13 +97,13 @@ describe('validateTrafficTypeExistance', () => { const validationPromise2 = validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_NOT_EXISTENT_ASYNC_TT, 'test_method_z'); expect(thenable(validationPromise2)).toBe(true); // If the storage is async, it should also return a promise. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_NOT_EXISTENT_ASYNC_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the async storage. - expect(loggerMock.warn.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. - expect(loggerMock.error.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.w.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.e.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. const isValid2 = await validationPromise2; expect(isValid2).toBe(false); // As the split is not on the storage, it will resolve to false, failing the validation.. - expect(loggerMock.warn.mock.calls).toEqual([[`test_method_z: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_ASYNC_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. - expect(loggerMock.error.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. + expect(loggerMock.w.mock.calls).toEqual([[`test_method_z: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_ASYNC_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. + expect(loggerMock.e.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. mockClear(); splitsCacheMock.trafficTypeExists.mockClear(); diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index 0a54963d..6b1e180b 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -11,14 +11,14 @@ function apiKeyError(reason: string) { return `Factory instantiation: ${reason}, export function validateApiKey(maybeApiKey: any): string | false { let apiKey: string | false = false; if (maybeApiKey == undefined) { // eslint-disable-line eqeqeq - log.error(apiKeyError('you passed a null or undefined api_key')); + log.e(apiKeyError('you passed a null or undefined api_key')); } else if (isString(maybeApiKey)) { if (maybeApiKey.length > 0) apiKey = maybeApiKey; else - log.error(apiKeyError('you passed an empty api_key')); + log.e(apiKeyError('you passed an empty api_key')); } else { - log.error(apiKeyError('you passed an invalid api_key')); + log.e(apiKeyError('you passed an invalid api_key')); } return apiKey; @@ -38,10 +38,10 @@ export function validateAndTrackApiKey(maybeApiKey: any): string | false { // If this key is not present, only warning scenarios is that we have factories for other keys. usedKeysMap[apiKey] = 1; if (Object.keys(usedKeysMap).length > 1) { - log.warn(apiKeyWarn('You already have an instance of the Split factory. Make sure you definitely want this additional instance')); + log.w(apiKeyWarn('You already have an instance of the Split factory. Make sure you definitely want this additional instance')); } } else { - log.warn(apiKeyWarn(`You already have ${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key`)); + log.w(apiKeyWarn(`You already have ${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key`)); usedKeysMap[apiKey]++; } } diff --git a/src/utils/inputValidation/attributes.ts b/src/utils/inputValidation/attributes.ts index a8e02e7f..4a3a0c33 100644 --- a/src/utils/inputValidation/attributes.ts +++ b/src/utils/inputValidation/attributes.ts @@ -8,6 +8,6 @@ export function validateAttributes(maybeAttrs: any, method: string): SplitIO.Att if (isObject(maybeAttrs) || maybeAttrs == undefined) // eslint-disable-line eqeqeq return maybeAttrs; - log.error(`${method}: attributes must be a plain object.`); + log.e(`${method}: attributes must be a plain object.`); return false; } diff --git a/src/utils/inputValidation/event.ts b/src/utils/inputValidation/event.ts index 70c78493..0fc2d282 100644 --- a/src/utils/inputValidation/event.ts +++ b/src/utils/inputValidation/event.ts @@ -6,14 +6,14 @@ const EVENT_TYPE_REGEX = /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/; export function validateEvent(maybeEvent: any, method: string): string | false { if (maybeEvent == undefined) { // eslint-disable-line eqeqeq - log.error(`${method}: you passed a null or undefined event_type, event_type must be a non-empty string.`); + log.e(`${method}: you passed a null or undefined event_type, event_type must be a non-empty string.`); } else if (!isString(maybeEvent)) { - log.error(`${method}: you passed an invalid event_type, event_type must be a non-empty string.`); + log.e(`${method}: you passed an invalid event_type, event_type must be a non-empty string.`); } else { // It is a string. if (maybeEvent.length === 0) { - log.error(`${method}: you passed an empty event_type, event_type must be a non-empty string.`); + log.e(`${method}: you passed an empty event_type, event_type must be a non-empty string.`); } else if (!EVENT_TYPE_REGEX.test(maybeEvent)) { - log.error(`${method}: you passed "${maybeEvent}", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.`); + log.e(`${method}: you passed "${maybeEvent}", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.`); } else { return maybeEvent; } diff --git a/src/utils/inputValidation/eventProperties.ts b/src/utils/inputValidation/eventProperties.ts index 980c2bfb..f2d2390d 100644 --- a/src/utils/inputValidation/eventProperties.ts +++ b/src/utils/inputValidation/eventProperties.ts @@ -17,7 +17,7 @@ export function validateEventProperties(maybeProperties: any, method: string): { if (maybeProperties == undefined) return { properties: null, size: BASE_EVENT_SIZE }; // eslint-disable-line eqeqeq if (!isObject(maybeProperties)) { - log.error(`${method}: properties must be a plain object.`); + log.e(`${method}: properties must be a plain object.`); return { properties: false, size: BASE_EVENT_SIZE }; } @@ -30,7 +30,7 @@ export function validateEventProperties(maybeProperties: any, method: string): { }; if (keys.length > MAX_PROPERTIES_AMOUNT) { - log.warn(`${method}: Event has more than 300 properties. Some of them will be trimmed when processed.`); + log.w(`${method}: Event has more than 300 properties. Some of them will be trimmed when processed.`); } for (let i = 0; i < keys.length; i++) { @@ -47,7 +47,7 @@ export function validateEventProperties(maybeProperties: any, method: string): { clone[keys[i]] = null; val = null; isNullVal = true; - log.warn(`${method}: Property ${keys[i]} is of invalid type. Setting value to null.`); + log.w(`${method}: Property ${keys[i]} is of invalid type. Setting value to null.`); } if (isNullVal) output.size += ECMA_SIZES.NULL; @@ -56,7 +56,7 @@ export function validateEventProperties(maybeProperties: any, method: string): { else if (isStringVal) output.size += val.length * ECMA_SIZES.STRING; if (output.size > MAX_PROPERTIES_SIZE) { - log.error(`${method}: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.`); + log.e(`${method}: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.`); output.properties = false; break; } diff --git a/src/utils/inputValidation/eventValue.ts b/src/utils/inputValidation/eventValue.ts index 07bff6ff..13e7bb29 100644 --- a/src/utils/inputValidation/eventValue.ts +++ b/src/utils/inputValidation/eventValue.ts @@ -6,6 +6,6 @@ export function validateEventValue(maybeValue: any, method: string): number | fa if (isFiniteNumber(maybeValue) || maybeValue == undefined) // eslint-disable-line eqeqeq return maybeValue; - log.error(`${method}: value must be a finite number.`); + log.e(`${method}: value must be a finite number.`); return false; } diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index 98a99c9d..5e8a77c7 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -5,13 +5,13 @@ const log = logFactory('', { displayAllErrors: true }); export function validateIfNotDestroyed(readinessManager: IReadinessManager): boolean { if (!readinessManager.isDestroyed()) return true; - log.error('Client has already been destroyed - no calls possible.'); + log.e('Client has already been destroyed - no calls possible.'); return false; } export function validateIfOperational(readinessManager: IReadinessManager, method: string) { if (readinessManager.isReady() || readinessManager.isReadyFromCache()) return true; - log.warn(`${method}: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.`); + log.w(`${method}: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.`); return false; } diff --git a/src/utils/inputValidation/key.ts b/src/utils/inputValidation/key.ts index 3805fe99..535583cd 100644 --- a/src/utils/inputValidation/key.ts +++ b/src/utils/inputValidation/key.ts @@ -7,11 +7,11 @@ const KEY_MAX_LENGTH = 250; function validateKeyValue(maybeKey: any, method: string, type: string): string | false { if (maybeKey == undefined) { // eslint-disable-line eqeqeq - log.error(`${method}: you passed a null or undefined ${type}, ${type} must be a non-empty string.`); + log.e(`${method}: you passed a null or undefined ${type}, ${type} must be a non-empty string.`); return false; } if (isFiniteNumber(maybeKey)) { - log.warn(`${method}: ${type} "${maybeKey}" is not of type string, converting.`); + log.w(`${method}: ${type} "${maybeKey}" is not of type string, converting.`); return toString(maybeKey); } if (isString(maybeKey)) { @@ -22,12 +22,12 @@ function validateKeyValue(maybeKey: any, method: string, type: string): string | if (maybeKey.length > 0 && maybeKey.length <= KEY_MAX_LENGTH) return maybeKey; if (maybeKey.length === 0) { - log.error(`${method}: you passed an empty string, ${type} must be a non-empty string.`); + log.e(`${method}: you passed an empty string, ${type} must be a non-empty string.`); } else if (maybeKey.length > KEY_MAX_LENGTH) { - log.error(`${method}: ${type} too long, ${type} must be 250 characters or less.`); + log.e(`${method}: ${type} too long, ${type} must be 250 characters or less.`); } } else { - log.error(`${method}: you passed an invalid ${type} type, ${type} must be a non-empty string.`); + log.e(`${method}: you passed an invalid ${type} type, ${type} must be a non-empty string.`); } return false; @@ -43,7 +43,7 @@ export function validateKey(maybeKey: any, method: string): SplitIO.SplitKey | f matchingKey, bucketingKey }; - log.error(`${method}: Key must be an object with bucketingKey and matchingKey with valid string properties.`); + log.e(`${method}: Key must be an object with bucketingKey and matchingKey with valid string properties.`); return false; } else { return validateKeyValue(maybeKey, method, 'key'); diff --git a/src/utils/inputValidation/preloadedData.ts b/src/utils/inputValidation/preloadedData.ts index 5936eb4b..a2432a90 100644 --- a/src/utils/inputValidation/preloadedData.ts +++ b/src/utils/inputValidation/preloadedData.ts @@ -6,18 +6,18 @@ const log = logFactory(''); function validateTimestampData(maybeTimestamp: any, method: string, item: string) { if (isFiniteNumber(maybeTimestamp) && maybeTimestamp > -1) return true; - log.error(`${method}: preloadedData.${item} must be a positive number.`); + log.e(`${method}: preloadedData.${item} must be a positive number.`); return false; } function validateSplitsData(maybeSplitsData: any, method: string) { if (isObject(maybeSplitsData)) { const splitNames = Object.keys(maybeSplitsData); - if (splitNames.length === 0) log.warn(`${method}: preloadedData.splitsData doesn't contain split definitions.`); + if (splitNames.length === 0) log.w(`${method}: preloadedData.splitsData doesn't contain split definitions.`); // @TODO in the future, consider handling the possibility of having parsed definitions of splits if (splitNames.every(splitName => validateSplit(splitName, method) && isString(maybeSplitsData[splitName]))) return true; } - log.error(`${method}: preloadedData.splitsData must be a map of split names to their serialized definitions.`); + log.e(`${method}: preloadedData.splitsData must be a map of split names to their serialized definitions.`); return false; } @@ -30,7 +30,7 @@ function validateMySegmentsData(maybeMySegmentsData: any, method: string) { return Array.isArray(segmentNames) && segmentNames.every(segmentName => isString(segmentName)); })) return true; } - log.error(`${method}: preloadedData.mySegmentsData must be a map of user keys to their list of segment names.`); + log.e(`${method}: preloadedData.mySegmentsData must be a map of user keys to their list of segment names.`); return false; } @@ -39,13 +39,13 @@ function validateSegmentsData(maybeSegmentsData: any, method: string) { const segmentNames = Object.keys(maybeSegmentsData); if (segmentNames.every(segmentName => isString(maybeSegmentsData[segmentName]))) return true; } - log.error(`${method}: preloadedData.segmentsData must be a map of segment names to their serialized definitions.`); + log.e(`${method}: preloadedData.segmentsData must be a map of segment names to their serialized definitions.`); return false; } export function validatePreloadedData(maybePreloadedData: any, method: string): maybePreloadedData is SplitIO.PreloadedData { if (!isObject(maybePreloadedData)) { - log.error(`${method}: preloadedData must be an object.`); + log.e(`${method}: preloadedData must be an object.`); } else if ( validateTimestampData(maybePreloadedData.lastUpdated, method, 'lastUpdated') && validateTimestampData(maybePreloadedData.since, method, 'since') && diff --git a/src/utils/inputValidation/split.ts b/src/utils/inputValidation/split.ts index 5204bb6f..a4b7771c 100644 --- a/src/utils/inputValidation/split.ts +++ b/src/utils/inputValidation/split.ts @@ -6,19 +6,19 @@ const TRIMMABLE_SPACES_REGEX = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/; export function validateSplit(maybeSplit: any, method: string, item = 'split name'): string | false { if (maybeSplit == undefined) { // eslint-disable-line eqeqeq - log.error(`${method}: you passed a null or undefined ${item}, ${item} must be a non-empty string.`); + log.e(`${method}: you passed a null or undefined ${item}, ${item} must be a non-empty string.`); } else if (!isString(maybeSplit)) { - log.error(`${method}: you passed an invalid ${item}, ${item} must be a non-empty string.`); + log.e(`${method}: you passed an invalid ${item}, ${item} must be a non-empty string.`); } else { if (TRIMMABLE_SPACES_REGEX.test(maybeSplit)) { - log.warn(`${method}: ${item} "${maybeSplit}" has extra whitespace, trimming.`); + log.w(`${method}: ${item} "${maybeSplit}" has extra whitespace, trimming.`); maybeSplit = maybeSplit.trim(); } if (maybeSplit.length > 0) { return maybeSplit; } else { - log.error(`${method}: you passed an empty ${item}, ${item} must be a non-empty string.`); + log.e(`${method}: you passed an empty ${item}, ${item} must be a non-empty string.`); } } diff --git a/src/utils/inputValidation/splitExistance.ts b/src/utils/inputValidation/splitExistance.ts index d8d34f58..1a92ff16 100644 --- a/src/utils/inputValidation/splitExistance.ts +++ b/src/utils/inputValidation/splitExistance.ts @@ -10,7 +10,7 @@ const log = logFactory(''); export function validateSplitExistance(readinessManager: IReadinessManager, splitName: string, labelOrSplitObj: any, method: string): boolean { if (readinessManager.isReady()) { // Only if it's ready we validate this, otherwise it may just be that the SDK is not ready yet. if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj == null) { - log.warn(`${method}: you passed "${splitName}" that does not exist in this environment, please double check what Splits exist in the web console.`); + log.w(`${method}: you passed "${splitName}" that does not exist in this environment, please double check what Splits exist in the web console.`); return false; } } diff --git a/src/utils/inputValidation/splits.ts b/src/utils/inputValidation/splits.ts index dade5173..795ad01f 100644 --- a/src/utils/inputValidation/splits.ts +++ b/src/utils/inputValidation/splits.ts @@ -16,6 +16,6 @@ export function validateSplits(maybeSplits: any, method: string, listName = 'spl if (validatedArray.length) return uniq(validatedArray); } - log.error(`${method}: ${listName} must be a non-empty array.`); + log.e(`${method}: ${listName} must be a non-empty array.`); return false; } diff --git a/src/utils/inputValidation/trafficType.ts b/src/utils/inputValidation/trafficType.ts index 05c9b36b..9b46fd79 100644 --- a/src/utils/inputValidation/trafficType.ts +++ b/src/utils/inputValidation/trafficType.ts @@ -6,15 +6,15 @@ const CAPITAL_LETTERS_REGEX = /[A-Z]/; export function validateTrafficType(maybeTT: any, method: string): string | false { if (maybeTT == undefined) { // eslint-disable-line eqeqeq - log.error(`${method}: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.`); + log.e(`${method}: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.`); } else if (!isString(maybeTT)) { - log.error(`${method}: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.`); + log.e(`${method}: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.`); } else { if (maybeTT.length === 0) { - log.error(`${method}: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.`); + log.e(`${method}: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.`); } else { if (CAPITAL_LETTERS_REGEX.test(maybeTT)) { - log.warn(`${method}: traffic_type_name should be all lowercase - converting string to lowercase.`); + log.w(`${method}: traffic_type_name should be all lowercase - converting string to lowercase.`); maybeTT = maybeTT.toLowerCase(); } diff --git a/src/utils/inputValidation/trafficTypeExistance.ts b/src/utils/inputValidation/trafficTypeExistance.ts index b54da612..a7044b67 100644 --- a/src/utils/inputValidation/trafficTypeExistance.ts +++ b/src/utils/inputValidation/trafficTypeExistance.ts @@ -8,7 +8,7 @@ import { MaybeThenable } from '../../dtos/types'; const log = logFactory(''); function logTTExistanceWarning(maybeTT: string, method: string) { - log.warn(`${method}: Traffic Type ${maybeTT} does not have any corresponding Splits in this environment, make sure you're tracking your events to a valid traffic type defined in the Split console.`); + log.w(`${method}: Traffic Type ${maybeTT} does not have any corresponding Splits in this environment, make sure you're tracking your events to a valid traffic type defined in the Split console.`); } /** diff --git a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts index ea1c52f5..e3a4eed0 100644 --- a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts +++ b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts @@ -20,25 +20,25 @@ describe('validateSplitFilters', () => { expect(validateSplitFilters(undefined, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array expect(validateSplitFilters(null, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls.length === 0).toBe(true); + expect(loggerMock.w.mock.calls.length === 0).toBe(true); expect(validateSplitFilters(true, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls[0]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); + expect(loggerMock.w.mock.calls[0]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); expect(validateSplitFilters(15, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls[1]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); + expect(loggerMock.w.mock.calls[1]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); expect(validateSplitFilters('string', STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls[2]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); + expect(loggerMock.w.mock.calls[2]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); expect(validateSplitFilters([], STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls[3]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); + expect(loggerMock.w.mock.calls[3]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); expect(validateSplitFilters([{ type: 'byName', values: ['split_1'] }], CONSUMER_MODE)).toEqual(defaultOutput); - expect(loggerMock.warn.mock.calls[4]).toEqual(["Factory instantiation: split filters have been configured but will have no effect if mode is not 'standalone', since synchronization is being deferred to an external tool."]); + expect(loggerMock.w.mock.calls[4]).toEqual(["Factory instantiation: split filters have been configured but will have no effect if mode is not 'standalone', since synchronization is being deferred to an external tool."]); - expect(loggerMock.debug.mock.calls.length === 0).toBe(true); - expect(loggerMock.error.mock.calls.length === 0).toBe(true); + expect(loggerMock.d.mock.calls.length === 0).toBe(true); + expect(loggerMock.e.mock.calls.length === 0).toBe(true); mockClear(); }); @@ -55,8 +55,8 @@ describe('validateSplitFilters', () => { groupedFilters: { byName: [], byPrefix: [] } }; expect(validateSplitFilters(splitFilters, STANDALONE_MODE)).toEqual(output); // filters without values - expect(loggerMock.debug.mock.calls[0]).toEqual(["Factory instantiation: splits filtering criteria is 'null'."]); - loggerMock.debug.mockClear(); + expect(loggerMock.d.mock.calls[0]).toEqual(["Factory instantiation: splits filtering criteria is 'null'."]); + loggerMock.d.mockClear(); splitFilters.push( { type: 'invalid', values: [] }, @@ -65,14 +65,14 @@ describe('validateSplitFilters', () => { { type: 'byName', values: [13] }); output.validFilters.push({ type: 'byName', values: [13] }); expect(validateSplitFilters(splitFilters, STANDALONE_MODE)).toEqual(output); // some filters are invalid - expect(loggerMock.debug.mock.calls).toEqual([["Factory instantiation: splits filtering criteria is 'null'."]]); - expect(loggerMock.warn.mock.calls).toEqual([ + expect(loggerMock.d.mock.calls).toEqual([["Factory instantiation: splits filtering criteria is 'null'."]]); + expect(loggerMock.w.mock.calls).toEqual([ ["Factory instantiation: split filter at position '3' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."], // invalid value of `type` property ["Factory instantiation: split filter at position '4' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."], // invalid type of `values` property ["Factory instantiation: split filter at position '5' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."] // invalid type of `type` property ]); - expect(loggerMock.error.mock.calls).toEqual([ + expect(loggerMock.e.mock.calls).toEqual([ ['Factory instantiation: you passed an invalid byName filter value, byName filter value must be a non-empty string.'], ['Factory instantiation: byName filter must be a non-empty array.'] ]); @@ -91,7 +91,7 @@ describe('validateSplitFilters', () => { groupedFilters: groupedFilters[i] }; expect(validateSplitFilters(splitFilters[i], STANDALONE_MODE)).toEqual(output); // splitFilters #${i} - expect(loggerMock.debug.mock.calls[loggerMock.debug.mock.calls.length - 1]).toEqual([`Factory instantiation: splits filtering criteria is '${queryStrings[i]}'.`]); + expect(loggerMock.d.mock.calls[loggerMock.d.mock.calls.length - 1]).toEqual([`Factory instantiation: splits filtering criteria is '${queryStrings[i]}'.`]); } else { // tests where validateSplitFilters throws an exception expect(() => validateSplitFilters(splitFilters[i], STANDALONE_MODE)).toThrow(queryStrings[i]); diff --git a/src/utils/settingsValidation/impressionsMode.ts b/src/utils/settingsValidation/impressionsMode.ts index cd14e43e..facff3e2 100644 --- a/src/utils/settingsValidation/impressionsMode.ts +++ b/src/utils/settingsValidation/impressionsMode.ts @@ -6,7 +6,7 @@ const log = logFactory('splitio-settings'); export default function validImpressionsMode(impressionsMode: string): SplitIO.ImpressionsMode { impressionsMode = impressionsMode.toUpperCase(); if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) === -1) { - log.error(`You passed an invalid impressionsMode, impressionsMode should be one of the following values: '${DEBUG}' or '${OPTIMIZED}'. Defaulting to '${OPTIMIZED}' mode.`); + log.e(`You passed an invalid impressionsMode, impressionsMode should be one of the following values: '${DEBUG}' or '${OPTIMIZED}'. Defaulting to '${OPTIMIZED}' mode.`); impressionsMode = OPTIMIZED; } diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index 850085b5..e7a61bde 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -21,7 +21,7 @@ export function validateIntegrations(settings: any, integrationValidator: (integ // Log a warning if at least one item is invalid const invalids = integrations.length - validIntegrations.length; - if (invalids) log.warn(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); + if (invalids) log.w(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); return validIntegrations; } diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index b62e5a40..5388acbd 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -96,12 +96,12 @@ export function validateSplitFilters(maybeSplitFilters: any, mode: string): ISpl if (!maybeSplitFilters) return res; // Warn depending on the mode if (mode !== STANDALONE_MODE) { - log.warn(`Factory instantiation: split filters have been configured but will have no effect if mode is not '${STANDALONE_MODE}', since synchronization is being deferred to an external tool.`); + log.w(`Factory instantiation: split filters have been configured but will have no effect if mode is not '${STANDALONE_MODE}', since synchronization is being deferred to an external tool.`); return res; } // Check collection type if (!Array.isArray(maybeSplitFilters) || maybeSplitFilters.length === 0) { - log.warn('Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'); + log.w('Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'); return res; } @@ -112,7 +112,7 @@ export function validateSplitFilters(maybeSplitFilters: any, mode: string): ISpl res.groupedFilters[filter.type as SplitIO.SplitFilterType] = res.groupedFilters[filter.type as SplitIO.SplitFilterType].concat(filter.values); return true; } else { - log.warn(`Factory instantiation: split filter at position '${index}' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'.`); + log.w(`Factory instantiation: split filter at position '${index}' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'.`); } return false; }); @@ -124,7 +124,7 @@ export function validateSplitFilters(maybeSplitFilters: any, mode: string): ISpl // build query string res.queryString = queryStringBuilder(res.groupedFilters); - log.debug(`Factory instantiation: splits filtering criteria is '${res.queryString}'.`); + log.d(`Factory instantiation: splits filtering criteria is '${res.queryString}'.`); return res; } diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index a0c03a76..11021ea2 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -17,7 +17,7 @@ export function validateStorageCS(settings: any): ISettings['storage'] { // @TODO validate its API (Splits cache, MySegments cache, etc) when supporting custom storages if (storage) { if (typeof storage === 'function') return storage; - log.warn('The provided storage is invalid. Fallbacking into default MEMORY storage'); + log.w('The provided storage is invalid. Fallbacking into default MEMORY storage'); } // return default InMemory storage if provided one is not valid diff --git a/src/utils/timeTracker/index.ts b/src/utils/timeTracker/index.ts index fa2dccb3..f3974bbc 100644 --- a/src/utils/timeTracker/index.ts +++ b/src/utils/timeTracker/index.ts @@ -205,7 +205,7 @@ const TrackerAPI = { if (timerData) { // Stop the timer and round result for readability. const et = timerData.timer(); - logger.debug(`[${task}] took ${et}ms to finish.`); + logger.d(`[${task}] took ${et}ms to finish.`); // Check if we have a tracker callback. if (timerData.cb) { From ce4a83df757cd9f1b7d319a0a567003ce5637ca7 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 25 Feb 2021 09:56:42 -0300 Subject: [PATCH 02/58] injected logger across evaluator modules --- src/evaluator/Engine.ts | 5 +- .../__tests__/evaluate-feature.spec.ts | 31 ++++--- .../__tests__/evaluate-features.spec.ts | 7 +- src/evaluator/combiners/__tests__/and.spec.ts | 5 +- .../combiners/__tests__/ifelseif.spec.ts | 7 +- src/evaluator/combiners/and.ts | 19 ++-- src/evaluator/combiners/ifelseif.ts | 45 +++++----- src/evaluator/condition/engineUtils.ts | 6 +- src/evaluator/index.ts | 28 +++--- src/evaluator/matchers/__tests__/all.spec.ts | 3 +- .../matchers/__tests__/between.spec.ts | 3 +- .../matchers/__tests__/boolean.spec.ts | 3 +- .../matchers/__tests__/cont_all.spec.ts | 3 +- .../matchers/__tests__/cont_any.spec.ts | 3 +- .../matchers/__tests__/cont_str.spec.ts | 3 +- .../matchers/__tests__/dependency.spec.ts | 23 ++--- src/evaluator/matchers/__tests__/eq.spec.ts | 3 +- .../matchers/__tests__/eq_set.spec.ts | 3 +- src/evaluator/matchers/__tests__/ew.spec.ts | 5 +- src/evaluator/matchers/__tests__/gte.spec.ts | 3 +- src/evaluator/matchers/__tests__/lte.spec.ts | 3 +- .../matchers/__tests__/part_of.spec.ts | 3 +- .../matchers/__tests__/regex.spec.ts | 7 +- .../__tests__/segment/client_side.spec.ts | 5 +- .../__tests__/segment/server_side.spec.ts | 3 +- src/evaluator/matchers/__tests__/sw.spec.ts | 3 +- .../matchers/__tests__/whitelist.spec.ts | 3 +- src/evaluator/matchers/all.ts | 17 ++-- src/evaluator/matchers/between.ts | 7 +- src/evaluator/matchers/boolean.ts | 7 +- src/evaluator/matchers/cont_all.ts | 7 +- src/evaluator/matchers/cont_any.ts | 7 +- src/evaluator/matchers/cont_str.ts | 7 +- src/evaluator/matchers/dependency.ts | 25 +++--- src/evaluator/matchers/eq.ts | 7 +- src/evaluator/matchers/eq_set.ts | 7 +- src/evaluator/matchers/ew.ts | 7 +- src/evaluator/matchers/gte.ts | 7 +- src/evaluator/matchers/index.ts | 5 +- src/evaluator/matchers/lte.ts | 7 +- src/evaluator/matchers/part_of.ts | 7 +- src/evaluator/matchers/segment.ts | 7 +- src/evaluator/matchers/string.ts | 7 +- src/evaluator/matchers/sw.ts | 7 +- src/evaluator/matchers/whitelist.ts | 7 +- .../parser/__tests__/boolean.spec.ts | 3 +- src/evaluator/parser/__tests__/index.spec.ts | 35 ++++---- .../parser/__tests__/invalidMatcher.spec.ts | 7 +- src/evaluator/parser/__tests__/regex.spec.ts | 3 +- src/evaluator/parser/__tests__/set.spec.ts | 87 ++++++++++--------- src/evaluator/parser/__tests__/string.spec.ts | 75 ++++++++-------- .../__tests__/trafficAllocation.spec.ts | 10 ++- src/evaluator/parser/index.ts | 11 +-- src/evaluator/types.ts | 3 +- src/evaluator/value/index.ts | 13 +-- src/evaluator/value/sanitize.ts | 7 +- src/logger/index.ts | 4 +- src/logger/noopLogger.ts | 8 ++ src/logger/types.ts | 10 +++ src/sdkClient/client.ts | 4 +- 60 files changed, 379 insertions(+), 288 deletions(-) create mode 100644 src/logger/noopLogger.ts diff --git a/src/evaluator/Engine.ts b/src/evaluator/Engine.ts index 96bd81bc..b9364b24 100644 --- a/src/evaluator/Engine.ts +++ b/src/evaluator/Engine.ts @@ -8,6 +8,7 @@ import { ISplit, MaybeThenable } from '../dtos/types'; import { SplitIO } from '../types'; import { IStorageAsync, IStorageSync } from '../storages/types'; import { IEvaluation, IEvaluationResult, IEvaluator, ISplitEvaluator } from './types'; +import { ILogger } from '../logger/types'; function evaluationResult(result: IEvaluation | undefined, defaultTreatment: string): IEvaluationResult { return { @@ -26,9 +27,9 @@ export default class Engine { } } - static parse(splitFlatStructure: ISplit, storage: IStorageSync | IStorageAsync) { + static parse(splitFlatStructure: ISplit, storage: IStorageSync | IStorageAsync, log: ILogger) { const conditions = splitFlatStructure.conditions; - const evaluator = parser(conditions, storage); + const evaluator = parser(log, conditions, storage); return new Engine(splitFlatStructure, evaluator); } diff --git a/src/evaluator/__tests__/evaluate-feature.spec.ts b/src/evaluator/__tests__/evaluate-feature.spec.ts index e5416a20..f4a9de8b 100644 --- a/src/evaluator/__tests__/evaluate-feature.spec.ts +++ b/src/evaluator/__tests__/evaluate-feature.spec.ts @@ -1,6 +1,7 @@ // @ts-nocheck import { evaluateFeature } from '../index'; import * as LabelsConstants from '../../utils/labels'; +import { noopLogger } from '../../logger/noopLogger'; const splitsMock = { regular: '{"changeNumber":1487277320548,"trafficAllocationSeed":1667452163,"trafficAllocation":100,"trafficTypeName":"user","name":"always-on","seed":1684183541,"configurations":{},"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"conditionType":"ROLLOUT","matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}', @@ -34,7 +35,8 @@ test('EVALUATOR / should return label exception, treatment control and config nu 'fake-key', 'throw_exception', null, - mockStorage + mockStorage, + noopLogger ); // This validation is async because the only exception possible when retrieving a Split would happen with Async storages. @@ -57,7 +59,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'config', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluationWithConfig).toEqual(expectedOutput); // If the split is retrieved successfully we should get the right evaluation result, label and config. @@ -65,7 +68,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'not_existent_split', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluationNotFound).toEqual(expectedOutputControl); // If the split is not retrieved successfully because it does not exist, we should get the right evaluation result, label and config. @@ -73,7 +77,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'regular', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluation).toEqual({ ...expectedOutput, config: null }); // If the split is retrieved successfully we should get the right evaluation result, label and config. If Split has no config it should have config equal null. @@ -81,7 +86,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'killed', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluationKilled).toEqual({ ...expectedOutput, treatment: 'off', config: null, label: LabelsConstants.SPLIT_KILLED }); // If the split is retrieved but is killed, we should get the right evaluation result, label and config. @@ -90,7 +96,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'archived', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluationArchived).toEqual({ ...expectedOutput, treatment: 'control', label: LabelsConstants.SPLIT_ARCHIVED, config: null }); // If the split is retrieved but is archived, we should get the right evaluation result, label and config. @@ -99,7 +106,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'trafficAlocation1', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluationtrafficAlocation1).toEqual({ ...expectedOutput, label: LabelsConstants.NOT_IN_SPLIT, config: null, treatment: 'off' }); // If the split is retrieved but is not in split (out of Traffic Allocation), we should get the right evaluation result, label and config. @@ -108,7 +116,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'killedWithConfig', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluationKilledWithConfig).toEqual({ ...expectedOutput, treatment: 'off', label: LabelsConstants.SPLIT_KILLED }); // If the split is retrieved but is killed, we should get the right evaluation result, label and config. @@ -117,7 +126,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'archivedWithConfig', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluationArchivedWithConfig).toEqual({ ...expectedOutput, treatment: 'control', label: LabelsConstants.SPLIT_ARCHIVED, config: null }); // If the split is retrieved but is archived, we should get the right evaluation result, label and config. @@ -126,7 +136,8 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'fake-key', 'trafficAlocation1WithConfig', null, - mockStorage + mockStorage, + noopLogger ); expect(evaluationtrafficAlocation1WithConfig).toEqual({ ...expectedOutput, label: LabelsConstants.NOT_IN_SPLIT, treatment: 'off' }); // If the split is retrieved but is not in split (out of Traffic Allocation), we should get the right evaluation result, label and config. diff --git a/src/evaluator/__tests__/evaluate-features.spec.ts b/src/evaluator/__tests__/evaluate-features.spec.ts index f5dc13b5..6ecd2f22 100644 --- a/src/evaluator/__tests__/evaluate-features.spec.ts +++ b/src/evaluator/__tests__/evaluate-features.spec.ts @@ -1,6 +1,7 @@ // @ts-nocheck import { evaluateFeatures } from '../index'; import * as LabelsConstants from '../../utils/labels'; +import { noopLogger } from '../../logger/noopLogger'; const splitsMock = { regular: '{"changeNumber":1487277320548,"trafficAllocationSeed":1667452163,"trafficAllocation":100,"trafficTypeName":"user","name":"always-on","seed":1684183541,"configurations":{},"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"conditionType":"ROLLOUT","matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}', @@ -46,7 +47,8 @@ test('EVALUATOR - Multiple evaluations at once / should return label exception, 'fake-key', ['throw_exception'], null, - mockStorage + mockStorage, + noopLogger ); expect(evaluation).toEqual(expectedOutput); // If there was an error on the `getSplits` we should get the results for exception. @@ -69,7 +71,8 @@ test('EVALUATOR - Multiple evaluations at once / should return right labels, tre 'fake-key', ['config', 'not_existent_split', 'regular', 'killed', 'archived', 'trafficAlocation1', 'killedWithConfig', 'archivedWithConfig', 'trafficAlocation1WithConfig'], null, - mockStorage + mockStorage, + noopLogger ); // assert evaluationWithConfig expect(multipleEvaluationAtOnce['config']).toEqual(expectedOutput['config']); // If the split is retrieved successfully we should get the right evaluation result, label and config. diff --git a/src/evaluator/combiners/__tests__/and.spec.ts b/src/evaluator/combiners/__tests__/and.spec.ts index cf52100a..0405499e 100644 --- a/src/evaluator/combiners/__tests__/and.spec.ts +++ b/src/evaluator/combiners/__tests__/and.spec.ts @@ -1,15 +1,16 @@ import andCombiner from '../and'; +import { noopLogger } from '../../../logger/noopLogger'; test('COMBINER AND / should always return true', async function () { - let AND = andCombiner([() => true, () => true, () => true]); + let AND = andCombiner([() => true, () => true, () => true], noopLogger); expect(await AND('always true')).toBe(true); // should always return true }); test('COMBINER AND / should always return false', async function () { - let AND = andCombiner([() => true, () => true, () => false]); + let AND = andCombiner([() => true, () => true, () => false], noopLogger); expect(await AND('always false')).toBe(false); // should always return false }); diff --git a/src/evaluator/combiners/__tests__/ifelseif.spec.ts b/src/evaluator/combiners/__tests__/ifelseif.spec.ts index 6783bb80..ef49c134 100644 --- a/src/evaluator/combiners/__tests__/ifelseif.spec.ts +++ b/src/evaluator/combiners/__tests__/ifelseif.spec.ts @@ -1,5 +1,6 @@ // @ts-nocheck import ifElseIfCombinerFactory from '../ifelseif'; +import { noopLogger } from '../../../logger/noopLogger'; test('IF ELSE IF COMBINER / should correctly propagate context parameters and predicates returns value', async function () { let inputKey = 'sample'; @@ -16,7 +17,7 @@ test('IF ELSE IF COMBINER / should correctly propagate context parameters and pr } let predicates = [evaluator]; - let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates); + let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, noopLogger); expect(await ifElseIfEvaluator(inputKey, inputSeed, inputAttributes) === evaluationResult).toBe(true); console.log(`evaluator should return ${evaluationResult}`); @@ -35,7 +36,7 @@ test('IF ELSE IF COMBINER / should stop evaluating when one matcher return a tre } ]; - let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates); + let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, noopLogger); expect(await ifElseIfEvaluator()).toBe('exclude'); // exclude treatment found }); @@ -53,7 +54,7 @@ test('IF ELSE IF COMBINER / should return undefined if there is none matching ru } ]; - const ifElseIfEvaluator = ifElseIfCombinerFactory(predicates); + const ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, noopLogger); expect(await ifElseIfEvaluator() === undefined).toBe(true); }); diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index 853cd639..b6fb61fb 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -1,19 +1,20 @@ import { findIndex } from '../../utils/lang'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:combiner'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:combiner'); +import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { MaybeThenable } from '../../dtos/types'; import { IMatcher } from '../types'; -function andResults(results: boolean[]): boolean { - // Array.prototype.every is supported by target environments - const hasMatchedAll = results.every(value => value); +export default function andCombinerContext(matchers: IMatcher[], log: ILogger) { - log.d(`[andCombiner] evaluates to ${hasMatchedAll}`); - return hasMatchedAll; -} + function andResults(results: boolean[]): boolean { + // Array.prototype.every is supported by target environments + const hasMatchedAll = results.every(value => value); -export default function andCombinerContext(matchers: IMatcher[]) { + log.d(`[andCombiner] evaluates to ${hasMatchedAll}`); + return hasMatchedAll; + } return function andCombiner(...params: any): MaybeThenable { const matcherResults = matchers.map(matcher => matcher(...params)); diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index 818b5302..c9e2be5e 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -1,39 +1,40 @@ import { findIndex } from '../../utils/lang'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:combiner'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:combiner'); +import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import * as LabelsConstants from '../../utils/labels'; import { CONTROL } from '../../utils/constants'; import { SplitIO } from '../../types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; -function unexpectedInputHandler() { - log.e('Invalid Split provided, no valid conditions found'); +export default function ifElseIfCombinerContext(predicates: IEvaluator[], log: ILogger): IEvaluator { - return { - treatment: CONTROL, - label: LabelsConstants.EXCEPTION - }; -} + function unexpectedInputHandler() { + log.e('Invalid Split provided, no valid conditions found'); -function computeTreatment(predicateResults: Array) { - const len = predicateResults.length; + return { + treatment: CONTROL, + label: LabelsConstants.EXCEPTION + }; + } - for (let i = 0; i < len; i++) { - const evaluation = predicateResults[i]; + function computeTreatment(predicateResults: Array) { + const len = predicateResults.length; - if (evaluation !== undefined) { - log.d(`Treatment found: ${evaluation.treatment}`); + for (let i = 0; i < len; i++) { + const evaluation = predicateResults[i]; - return evaluation; - } - } + if (evaluation !== undefined) { + log.d(`Treatment found: ${evaluation.treatment}`); - log.d('All predicates evaluated, no treatment found.'); - return undefined; -} + return evaluation; + } + } -export default function ifElseIfCombinerContext(predicates: IEvaluator[]): IEvaluator { + log.d('All predicates evaluated, no treatment found.'); + return undefined; + } function ifElseIfCombiner(key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) { // In Async environments we are going to have async predicates. There is none way to know diff --git a/src/evaluator/condition/engineUtils.ts b/src/evaluator/condition/engineUtils.ts index 7b5a4925..78cbac09 100644 --- a/src/evaluator/condition/engineUtils.ts +++ b/src/evaluator/condition/engineUtils.ts @@ -1,6 +1,6 @@ import { bucket } from '../../utils/murmur3/murmur3'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine'); /** * Get the treatment name given a key, a seed, and the percentage of each treatment. @@ -10,7 +10,7 @@ export function getTreatment(key: string, seed: number, treatments: { getTreatme const treatment = treatments.getTreatmentFor(_bucket); - log.d(`[engine] using algo 'murmur' bucket ${_bucket} for key ${key} using seed ${seed} - treatment ${treatment}`); + // log.debug(`[engine] using algo 'murmur' bucket ${_bucket} for key ${key} using seed ${seed} - treatment ${treatment}`); return treatment; } diff --git a/src/evaluator/index.ts b/src/evaluator/index.ts index 02407bef..619b9e97 100644 --- a/src/evaluator/index.ts +++ b/src/evaluator/index.ts @@ -7,6 +7,7 @@ import { ISplit, MaybeThenable } from '../dtos/types'; import { IStorageAsync, IStorageSync } from '../storages/types'; import { IEvaluationResult } from './types'; import { SplitIO } from '../types'; +import { ILogger } from '../logger/types'; const treatmentException = { treatment: CONTROL, @@ -18,7 +19,8 @@ export function evaluateFeature( key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, - storage: IStorageSync | IStorageAsync + storage: IStorageSync | IStorageAsync, + log: ILogger ): MaybeThenable { let stringifiedSplit; @@ -36,7 +38,8 @@ export function evaluateFeature( result, key, attributes, - storage + storage, + log )); } @@ -44,7 +47,8 @@ export function evaluateFeature( stringifiedSplit, key, attributes, - storage + storage, + log ); } @@ -52,7 +56,8 @@ export function evaluateFeatures( key: SplitIO.SplitKey, splitNames: string[], attributes: SplitIO.Attributes | undefined, - storage: IStorageSync | IStorageAsync + storage: IStorageSync | IStorageAsync, + log: ILogger ): MaybeThenable> { let stringifiedSplits; const evaluations: Record = {}; @@ -70,15 +75,16 @@ export function evaluateFeatures( } return (thenable(stringifiedSplits)) ? - stringifiedSplits.then(splits => getEvaluations(splitNames, splits, key, attributes, storage)) : - getEvaluations(splitNames, stringifiedSplits, key, attributes, storage); + stringifiedSplits.then(splits => getEvaluations(splitNames, splits, key, attributes, storage, log)) : + getEvaluations(splitNames, stringifiedSplits, key, attributes, storage, log); } function getEvaluation( stringifiedSplit: string | null, key: SplitIO.SplitKey, attributes: SplitIO.Attributes | undefined, - storage: IStorageSync | IStorageAsync + storage: IStorageSync | IStorageAsync, + log: ILogger ): MaybeThenable { let evaluation: MaybeThenable = { treatment: CONTROL, @@ -88,7 +94,7 @@ function getEvaluation( if (stringifiedSplit) { const splitJSON: ISplit = JSON.parse(stringifiedSplit); - const split = Engine.parse(splitJSON, storage); + const split = Engine.parse(splitJSON, storage, log); evaluation = split.getTreatment(key, attributes, evaluateFeature); // If the storage is async, evaluation and changeNumber will return a thenable @@ -113,7 +119,8 @@ function getEvaluations( splits: Record, key: SplitIO.SplitKey, attributes: SplitIO.Attributes | undefined, - storage: IStorageSync | IStorageAsync + storage: IStorageSync | IStorageAsync, + log: ILogger ): MaybeThenable> { const result: Record = {}; const thenables: Promise[] = []; @@ -122,7 +129,8 @@ function getEvaluations( splits[splitName], key, attributes, - storage + storage, + log ); if (thenable(evaluation)) { thenables.push(evaluation.then(res => { diff --git a/src/evaluator/matchers/__tests__/all.spec.ts b/src/evaluator/matchers/__tests__/all.spec.ts index 2f5f44ec..b2d8b54e 100644 --- a/src/evaluator/matchers/__tests__/all.spec.ts +++ b/src/evaluator/matchers/__tests__/all.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER ALL_KEYS / should always return true', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { type: matcherTypes.ALL_KEYS, value: undefined } as IMatcherDto) as IMatcher; diff --git a/src/evaluator/matchers/__tests__/between.spec.ts b/src/evaluator/matchers/__tests__/between.spec.ts index d3b1840a..d379b035 100644 --- a/src/evaluator/matchers/__tests__/between.spec.ts +++ b/src/evaluator/matchers/__tests__/between.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER BETWEEN / should return true ONLY when the value is between 10 and 20', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.BETWEEN, value: { diff --git a/src/evaluator/matchers/__tests__/boolean.spec.ts b/src/evaluator/matchers/__tests__/boolean.spec.ts index d03ee30f..16664423 100644 --- a/src/evaluator/matchers/__tests__/boolean.spec.ts +++ b/src/evaluator/matchers/__tests__/boolean.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER BOOLEAN / should return true ONLY when the value is true', function () { // @ts-ignore - const matcher = matcherFactory({ + const matcher = matcherFactory(noopLogger, { type: matcherTypes.EQUAL_TO_BOOLEAN, value: true } as IMatcherDto) as IMatcher; diff --git a/src/evaluator/matchers/__tests__/cont_all.spec.ts b/src/evaluator/matchers/__tests__/cont_all.spec.ts index 4acaac65..4f72cec1 100644 --- a/src/evaluator/matchers/__tests__/cont_all.spec.ts +++ b/src/evaluator/matchers/__tests__/cont_all.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER CONTAINS_ALL_OF_SET / should return true ONLY when value contains all of set ["update", "add"]', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.CONTAINS_ALL_OF_SET, value: ['update', 'add'] diff --git a/src/evaluator/matchers/__tests__/cont_any.spec.ts b/src/evaluator/matchers/__tests__/cont_any.spec.ts index 87d40b22..257d153a 100644 --- a/src/evaluator/matchers/__tests__/cont_any.spec.ts +++ b/src/evaluator/matchers/__tests__/cont_any.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER CONTAINS_ANY_OF_SET / should return true ONLY when value contains any of set ["update", "add"]', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.CONTAINS_ANY_OF_SET, value: ['update', 'add'] diff --git a/src/evaluator/matchers/__tests__/cont_str.spec.ts b/src/evaluator/matchers/__tests__/cont_str.spec.ts index 91aead24..b365d5d2 100644 --- a/src/evaluator/matchers/__tests__/cont_str.spec.ts +++ b/src/evaluator/matchers/__tests__/cont_str.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER CONTAINS_STRING / should return true ONLY when the value is contained in ["roni", "bad", "ar"]', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.CONTAINS_STRING, value: ['roni', 'bad', 'ar'] diff --git a/src/evaluator/matchers/__tests__/dependency.spec.ts b/src/evaluator/matchers/__tests__/dependency.spec.ts index 5e7cd5b3..f90ce7f8 100644 --- a/src/evaluator/matchers/__tests__/dependency.spec.ts +++ b/src/evaluator/matchers/__tests__/dependency.spec.ts @@ -3,6 +3,7 @@ import matcherFactory from '..'; import { evaluateFeature } from '../../index'; import { IMatcher, IMatcherDto } from '../../types'; import { IStorageSync } from '../../../storages/types'; +import { noopLogger } from '../../../logger/noopLogger'; const ALWAYS_ON_SPLIT = '{"trafficTypeName":"user","name":"always-on","trafficAllocation":100,"trafficAllocationSeed":1012950810,"seed":-725161385,"status":"ACTIVE","killed":false,"defaultTreatment":"off","changeNumber":1494364996459,"algo":2,"conditions":[{"conditionType":"ROLLOUT","matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":null},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":null,"whitelistMatcherData":null,"unaryNumericMatcherData":null,"betweenMatcherData":null}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'; const ALWAYS_OFF_SPLIT = '{"trafficTypeName":"user","name":"always-off","trafficAllocation":100,"trafficAllocationSeed":-331690370,"seed":403891040,"status":"ACTIVE","killed":false,"defaultTreatment":"on","changeNumber":1494365020316,"algo":2,"conditions":[{"conditionType":"ROLLOUT","matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":null},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":null,"whitelistMatcherData":null,"unaryNumericMatcherData":null,"betweenMatcherData":null}]},"partitions":[{"treatment":"on","size":0},{"treatment":"off","size":100}],"label":"in segment all"}]}'; @@ -18,7 +19,7 @@ const mockStorage = { }; test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split returns one of the expected treatments', function () { - const matcherTrueAlwaysOn = matcherFactory({ + const matcherTrueAlwaysOn = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', @@ -26,7 +27,7 @@ test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split ret } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherFalseAlwaysOn = matcherFactory({ + const matcherFalseAlwaysOn = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', @@ -34,7 +35,7 @@ test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split ret } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherTrueAlwaysOff = matcherFactory({ + const matcherTrueAlwaysOff = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-off', @@ -42,7 +43,7 @@ test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split ret } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherFalseAlwaysOff = matcherFactory({ + const matcherFalseAlwaysOff = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-off', @@ -57,7 +58,7 @@ test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split ret }); test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { - const matcherParentNotExist = matcherFactory({ + const matcherParentNotExist = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'not-existent-split', @@ -66,7 +67,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; // @ts-ignore - const matcherNoTreatmentsExpected = matcherFactory({ + const matcherNoTreatmentsExpected = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', @@ -75,7 +76,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; // @ts-ignore - const matcherParentNameEmpty = matcherFactory({ + const matcherParentNameEmpty = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: '', @@ -84,7 +85,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; // @ts-ignore - const matcherParentNameWrongType = matcherFactory({ + const matcherParentNameWrongType = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: { some: 44 }, @@ -92,7 +93,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherExpectedTreatmentWrongTypeMatching = matcherFactory({ + const matcherExpectedTreatmentWrongTypeMatching = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', @@ -100,7 +101,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherExpectedTreatmentWrongTypeNotMatching = matcherFactory({ + const matcherExpectedTreatmentWrongTypeNotMatching = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-off', @@ -110,7 +111,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; // @ts-ignore - const matcherExpectationsListWrongType = matcherFactory({ + const matcherExpectationsListWrongType = matcherFactory(noopLogger, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', diff --git a/src/evaluator/matchers/__tests__/eq.spec.ts b/src/evaluator/matchers/__tests__/eq.spec.ts index 99380de4..d2d03395 100644 --- a/src/evaluator/matchers/__tests__/eq.spec.ts +++ b/src/evaluator/matchers/__tests__/eq.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER EQUAL / should return true ONLY when the value is equal to 10', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.EQUAL_TO, value: 10 diff --git a/src/evaluator/matchers/__tests__/eq_set.spec.ts b/src/evaluator/matchers/__tests__/eq_set.spec.ts index 49bc1c72..ab713024 100644 --- a/src/evaluator/matchers/__tests__/eq_set.spec.ts +++ b/src/evaluator/matchers/__tests__/eq_set.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER EQUAL_TO_SET / should return true ONLY when value is equal to set ["update", "add"]', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.EQUAL_TO_SET, value: ['update', 'add'] diff --git a/src/evaluator/matchers/__tests__/ew.spec.ts b/src/evaluator/matchers/__tests__/ew.spec.ts index e058d239..db8fc07f 100644 --- a/src/evaluator/matchers/__tests__/ew.spec.ts +++ b/src/evaluator/matchers/__tests__/ew.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER ENDS_WITH / should return true ONLY when the value ends with ["a", "b", "c"]', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.ENDS_WITH, value: ['a', 'b', 'c'] @@ -19,7 +20,7 @@ test('MATCHER ENDS_WITH / should return true ONLY when the value ends with ["a", test('MATCHER ENDS_WITH / should return true ONLY when the value ends with ["demo.test.org"]', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.ENDS_WITH, value: ['demo.test.org'] diff --git a/src/evaluator/matchers/__tests__/gte.spec.ts b/src/evaluator/matchers/__tests__/gte.spec.ts index 030dd2a8..c65c3ed1 100644 --- a/src/evaluator/matchers/__tests__/gte.spec.ts +++ b/src/evaluator/matchers/__tests__/gte.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER GREATER THAN OR EQUAL / should return true ONLY when the value is greater than or equal to 10', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.GREATER_THAN_OR_EQUAL_TO, value: 10 diff --git a/src/evaluator/matchers/__tests__/lte.spec.ts b/src/evaluator/matchers/__tests__/lte.spec.ts index d592c5b5..addffbf0 100644 --- a/src/evaluator/matchers/__tests__/lte.spec.ts +++ b/src/evaluator/matchers/__tests__/lte.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER LESS THAN OR EQUAL / should return true ONLY when the value is less than or equal to 10', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.LESS_THAN_OR_EQUAL_TO, value: 10 diff --git a/src/evaluator/matchers/__tests__/part_of.spec.ts b/src/evaluator/matchers/__tests__/part_of.spec.ts index a68c371b..6cfcb53f 100644 --- a/src/evaluator/matchers/__tests__/part_of.spec.ts +++ b/src/evaluator/matchers/__tests__/part_of.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER PART_OF_SET / should return true ONLY when value is part of of set ["update", "add", "delete"]', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.PART_OF_SET, value: ['update', 'add', 'delete'] diff --git a/src/evaluator/matchers/__tests__/regex.spec.ts b/src/evaluator/matchers/__tests__/regex.spec.ts index a68005ba..3ce1e1f3 100644 --- a/src/evaluator/matchers/__tests__/regex.spec.ts +++ b/src/evaluator/matchers/__tests__/regex.spec.ts @@ -3,10 +3,11 @@ import matcherFactory from '..'; import fs from 'fs'; import rl from 'readline'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER REGEX (STRING) / should match the attribute value only with the string starts with hello', function () { // @ts-ignore - const matcher = matcherFactory({ + const matcher = matcherFactory(noopLogger, { type: matcherTypes.MATCHES_STRING, value: '^hello' } as IMatcherDto) as IMatcher; @@ -17,7 +18,7 @@ test('MATCHER REGEX (STRING) / should match the attribute value only with the st test('MATCHER REGEX (STRING) / incorrectly matches unicode characters', function () { // @ts-ignore - const matcher = matcherFactory({ + const matcher = matcherFactory(noopLogger, { type: matcherTypes.MATCHES_STRING, value: 'a.b' } as IMatcherDto) as IMatcher; @@ -46,7 +47,7 @@ test('MATCHER REGEX (STRING) / incorrectly matches unicode characters', function const isTestTrue = test === 'true'; // @ts-ignore - const matcher = matcherFactory({ + const matcher = matcherFactory(noopLogger, { type: matcherTypes.MATCHES_STRING, value: regex } as IMatcherDto) as IMatcher; diff --git a/src/evaluator/matchers/__tests__/segment/client_side.spec.ts b/src/evaluator/matchers/__tests__/segment/client_side.spec.ts index 09d57789..66941ed8 100644 --- a/src/evaluator/matchers/__tests__/segment/client_side.spec.ts +++ b/src/evaluator/matchers/__tests__/segment/client_side.spec.ts @@ -2,11 +2,12 @@ import { matcherTypes } from '../../matcherTypes'; import matcherFactory from '../..'; import { IMatcher, IMatcherDto } from '../../../types'; import { IStorageSync } from '../../../../storages/types'; +import { noopLogger } from '../../../../logger/noopLogger'; test('MATCHER IN_SEGMENT / should return true ONLY when the segment is defined inside the segment storage', async function () { const segment = 'employees'; - const matcherTrue = matcherFactory({ + const matcherTrue = matcherFactory(noopLogger, { type: matcherTypes.IN_SEGMENT, value: segment } as IMatcherDto, { @@ -17,7 +18,7 @@ test('MATCHER IN_SEGMENT / should return true ONLY when the segment is defined i } } as IStorageSync) as IMatcher; - const matcherFalse = matcherFactory({ + const matcherFalse = matcherFactory(noopLogger, { type: matcherTypes.IN_SEGMENT, value: segment + 'asd' } as IMatcherDto, { diff --git a/src/evaluator/matchers/__tests__/segment/server_side.spec.ts b/src/evaluator/matchers/__tests__/segment/server_side.spec.ts index 38b7ae70..b056608b 100644 --- a/src/evaluator/matchers/__tests__/segment/server_side.spec.ts +++ b/src/evaluator/matchers/__tests__/segment/server_side.spec.ts @@ -2,11 +2,12 @@ import { matcherTypes } from '../../matcherTypes'; import matcherFactory from '../..'; import { IMatcher, IMatcherDto } from '../../../types'; import { IStorageSync } from '../../../../storages/types'; +import { noopLogger } from '../../../../logger/noopLogger'; test('MATCHER IN_SEGMENT / should return true ONLY when the key is defined inside the segment', async function () { const segment = 'employees'; - const matcher = matcherFactory({ + const matcher = matcherFactory(noopLogger, { type: matcherTypes.IN_SEGMENT, value: segment } as IMatcherDto, { diff --git a/src/evaluator/matchers/__tests__/sw.spec.ts b/src/evaluator/matchers/__tests__/sw.spec.ts index 59787aa2..dd282b0d 100644 --- a/src/evaluator/matchers/__tests__/sw.spec.ts +++ b/src/evaluator/matchers/__tests__/sw.spec.ts @@ -1,10 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER STARTS_WITH / should return true ONLY when the value starts with ["a", "b", "c"]', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { negate: false, type: matcherTypes.STARTS_WITH, value: ['a', 'b', 'c'] diff --git a/src/evaluator/matchers/__tests__/whitelist.spec.ts b/src/evaluator/matchers/__tests__/whitelist.spec.ts index 9ffb4369..a2e43420 100644 --- a/src/evaluator/matchers/__tests__/whitelist.spec.ts +++ b/src/evaluator/matchers/__tests__/whitelist.spec.ts @@ -2,10 +2,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { _Set } from '../../../utils/lang/sets'; import { IMatcher, IMatcherDto } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('MATCHER WHITELIST / should return true ONLY when the key is defined', function () { // @ts-ignore - let matcher = matcherFactory({ + let matcher = matcherFactory(noopLogger, { type: matcherTypes.WHITELIST, value: new _Set().add('key') } as IMatcherDto) as IMatcher; diff --git a/src/evaluator/matchers/all.ts b/src/evaluator/matchers/all.ts index 0fec9b93..a186f40d 100644 --- a/src/evaluator/matchers/all.ts +++ b/src/evaluator/matchers/all.ts @@ -1,12 +1,11 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -function allMatcher(runtimeAttr: string): boolean { - log.d('[allMatcher] is always true'); +export default function allMatcherContext(log: ILogger) { + return function allMatcher(runtimeAttr: string): boolean { + log.d('[allMatcher] is always true'); - return runtimeAttr != null; -} - -export default function allMatcherContext() { - return allMatcher; + return runtimeAttr != null; + }; } diff --git a/src/evaluator/matchers/between.ts b/src/evaluator/matchers/between.ts index bedf3a7e..bdb2e899 100644 --- a/src/evaluator/matchers/between.ts +++ b/src/evaluator/matchers/between.ts @@ -1,8 +1,9 @@ import { IBetweenMatcherData } from '../../dtos/types'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function betweenMatcherContext(ruleVO: IBetweenMatcherData) /*: Function */ { +export default function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatcherData) /*: Function */ { return function betweenMatcher(runtimeAttr: number): boolean { let isBetween = runtimeAttr >= ruleVO.start && runtimeAttr <= ruleVO.end; diff --git a/src/evaluator/matchers/boolean.ts b/src/evaluator/matchers/boolean.ts index 3b35967f..daba4766 100644 --- a/src/evaluator/matchers/boolean.ts +++ b/src/evaluator/matchers/boolean.ts @@ -1,7 +1,8 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function booleanMatcherContext(ruleAttr: boolean) /*: Function */ { +export default function booleanMatcherContext(log: ILogger, ruleAttr: boolean) /*: Function */ { return function booleanMatcher(runtimeAttr: boolean): boolean { let booleanMatches = ruleAttr === runtimeAttr; diff --git a/src/evaluator/matchers/cont_all.ts b/src/evaluator/matchers/cont_all.ts index 68bfaf12..ae5842c1 100644 --- a/src/evaluator/matchers/cont_all.ts +++ b/src/evaluator/matchers/cont_all.ts @@ -1,8 +1,9 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; -export default function containsAllMatcherContext(ruleAttr: string[]) /*: Function */ { +export default function containsAllMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function containsAllMatcher(runtimeAttr: string[]): boolean { let containsAll = true; diff --git a/src/evaluator/matchers/cont_any.ts b/src/evaluator/matchers/cont_any.ts index 569873fd..f1b8ae90 100644 --- a/src/evaluator/matchers/cont_any.ts +++ b/src/evaluator/matchers/cont_any.ts @@ -1,8 +1,9 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; -export default function containsAnyMatcherContext(ruleAttr: string[]) /*: Function */ { +export default function containsAnyMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function containsAnyMatcher(runtimeAttr: string[]): boolean { let containsAny = false; diff --git a/src/evaluator/matchers/cont_str.ts b/src/evaluator/matchers/cont_str.ts index 72cf50b2..6f9d61c7 100644 --- a/src/evaluator/matchers/cont_str.ts +++ b/src/evaluator/matchers/cont_str.ts @@ -1,8 +1,9 @@ import { isString } from '../../utils/lang'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function containsStringMatcherContext(ruleAttr: string[]) /*: Function */ { +export default function containsStringMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function containsStringMatcher(runtimeAttr: string): boolean { let contains = ruleAttr.some(e => isString(runtimeAttr) && runtimeAttr.indexOf(e) > -1); diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index 36692a9c..ba95c965 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -1,27 +1,28 @@ import { IDependencyMatcherData, MaybeThenable } from '../../dtos/types'; -import { logFactory } from '../../logger/sdkLogger'; import { IStorageAsync, IStorageSync } from '../../storages/types'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { IDependencyMatcherValue, IEvaluation, ISplitEvaluator } from '../types'; -function checkTreatment(evaluation: IEvaluation, acceptableTreatments: string[], parentName: string) { - let matches = false; +export default function dependencyMatcherContext(log: ILogger, { split, treatments }: IDependencyMatcherData, storage: IStorageSync | IStorageAsync) { - if (Array.isArray(acceptableTreatments)) { - matches = acceptableTreatments.indexOf(evaluation.treatment as string) !== -1; - } + function checkTreatment(evaluation: IEvaluation, acceptableTreatments: string[], parentName: string) { + let matches = false; - log.d(`[dependencyMatcher] Parent split "${parentName}" evaluated to "${evaluation.treatment}" with label "${evaluation.label}". ${parentName} evaluated treatment is part of [${acceptableTreatments}] ? ${matches}.`); + if (Array.isArray(acceptableTreatments)) { + matches = acceptableTreatments.indexOf(evaluation.treatment as string) !== -1; + } - return matches; -} + log.d(`[dependencyMatcher] Parent split "${parentName}" evaluated to "${evaluation.treatment}" with label "${evaluation.label}". ${parentName} evaluated treatment is part of [${acceptableTreatments}] ? ${matches}.`); -export default function dependencyMatcherContext({ split, treatments }: IDependencyMatcherData, storage: IStorageSync | IStorageAsync) { + return matches; + } return function dependencyMatcher({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator): MaybeThenable { log.d(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? `\n attributes: ${JSON.stringify(attributes)}` : ''}`); - const evaluation = splitEvaluator(key, split, attributes, storage); + const evaluation = splitEvaluator(key, split, attributes, storage, log); if (thenable(evaluation)) { return evaluation.then(ev => checkTreatment(ev, treatments, split)); diff --git a/src/evaluator/matchers/eq.ts b/src/evaluator/matchers/eq.ts index 16a44f4c..71e3b924 100644 --- a/src/evaluator/matchers/eq.ts +++ b/src/evaluator/matchers/eq.ts @@ -1,7 +1,8 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function equalToMatcherContext(ruleAttr: number) /*: Function */ { +export default function equalToMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ { return function equalToMatcher(runtimeAttr: number): boolean { let isEqual = runtimeAttr === ruleAttr; diff --git a/src/evaluator/matchers/eq_set.ts b/src/evaluator/matchers/eq_set.ts index 01c0a118..a53e6f16 100644 --- a/src/evaluator/matchers/eq_set.ts +++ b/src/evaluator/matchers/eq_set.ts @@ -1,8 +1,9 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; -export default function equalToSetMatcherContext(ruleAttr: string[]) /*: Function */ { +export default function equalToSetMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function equalToSetMatcher(runtimeAttr: string[]): boolean { // Length being the same is the first condition. let isEqual = runtimeAttr.length === ruleAttr.length; diff --git a/src/evaluator/matchers/ew.ts b/src/evaluator/matchers/ew.ts index 86f57a04..d7cf5178 100644 --- a/src/evaluator/matchers/ew.ts +++ b/src/evaluator/matchers/ew.ts @@ -1,8 +1,9 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; import { endsWith as strEndsWith } from '../../utils/lang'; -export default function endsWithMatcherContext(ruleAttr: string[]) /*: Function */ { +export default function endsWithMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function endsWithMatcher(runtimeAttr: string): boolean { let endsWith = ruleAttr.some(e => strEndsWith(runtimeAttr, e)); diff --git a/src/evaluator/matchers/gte.ts b/src/evaluator/matchers/gte.ts index c4374e48..fb89f48c 100644 --- a/src/evaluator/matchers/gte.ts +++ b/src/evaluator/matchers/gte.ts @@ -1,7 +1,8 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function greaterThanEqualMatcherContext(ruleAttr: number) /*: Function */ { +export default function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ { return function greaterThanEqualMatcher(runtimeAttr: number): boolean { let isGreaterEqualThan = runtimeAttr >= ruleAttr; diff --git a/src/evaluator/matchers/index.ts b/src/evaluator/matchers/index.ts index 07d1af91..8cf50779 100644 --- a/src/evaluator/matchers/index.ts +++ b/src/evaluator/matchers/index.ts @@ -17,6 +17,7 @@ import booleanMatcher from './boolean'; import stringMatcher from './string'; import { IStorageAsync, IStorageSync } from '../../storages/types'; import { IMatcher, IMatcherDto } from '../types'; +import { ILogger } from '../../logger/types'; const matchers = [ undefined, // UNDEFINED: 0, @@ -42,7 +43,7 @@ const matchers = [ /** * Matcher factory. */ -export default function matcherFactory(matcherDto: IMatcherDto, storage?: IStorageSync | IStorageAsync): IMatcher | undefined { +export default function matcherFactory(log: ILogger, matcherDto: IMatcherDto, storage?: IStorageSync | IStorageAsync): IMatcher | undefined { let { type, value @@ -50,6 +51,6 @@ export default function matcherFactory(matcherDto: IMatcherDto, storage?: IStora let matcherFn; // @ts-ignore - if (matchers[type]) matcherFn = matchers[type](value, storage); // There is no index-out-of-bound exception in JavaScript + if (matchers[type]) matcherFn = matchers[type](log, value, storage); // There is no index-out-of-bound exception in JavaScript return matcherFn; } diff --git a/src/evaluator/matchers/lte.ts b/src/evaluator/matchers/lte.ts index 84213ab7..9b9720fd 100644 --- a/src/evaluator/matchers/lte.ts +++ b/src/evaluator/matchers/lte.ts @@ -1,7 +1,8 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function lessThanEqualMatcherContext(ruleAttr: number) /*: function */ { +export default function lessThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: function */ { return function lessThanEqualMatcher(runtimeAttr: number): boolean { let isLessEqualThan = runtimeAttr <= ruleAttr; diff --git a/src/evaluator/matchers/part_of.ts b/src/evaluator/matchers/part_of.ts index 0cd63b49..7288f611 100644 --- a/src/evaluator/matchers/part_of.ts +++ b/src/evaluator/matchers/part_of.ts @@ -1,8 +1,9 @@ -import { logFactory } from '../../logger/sdkLogger'; import { findIndex } from '../../utils/lang'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function partOfMatcherContext(ruleAttr: string[]) /*: Function */ { +export default function partOfMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function partOfMatcher(runtimeAttr: string[]): boolean { // To be part of the length should be minor or equal. let isPartOf = runtimeAttr.length <= ruleAttr.length; diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index af05422b..0c574745 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -1,10 +1,11 @@ import { MaybeThenable } from '../../dtos/types'; -import { logFactory } from '../../logger/sdkLogger'; import { ISegmentsCacheBase } from '../../storages/types'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; -export default function matcherSegmentContext(segmentName: string, storage: { segments: ISegmentsCacheBase }) { +export default function matcherSegmentContext(log: ILogger, segmentName: string, storage: { segments: ISegmentsCacheBase }) { return function segmentMatcher(key: string): MaybeThenable { const isInSegment = storage.segments.isInSegment(segmentName, key); diff --git a/src/evaluator/matchers/string.ts b/src/evaluator/matchers/string.ts index 8df2a17e..f955c234 100644 --- a/src/evaluator/matchers/string.ts +++ b/src/evaluator/matchers/string.ts @@ -1,7 +1,8 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function stringMatcherContext(ruleAttr: string) /*: Function */ { +export default function stringMatcherContext(log: ILogger, ruleAttr: string) /*: Function */ { return function stringMatcher(runtimeAttr: string): boolean { let re; diff --git a/src/evaluator/matchers/sw.ts b/src/evaluator/matchers/sw.ts index 39dbdcda..d0d8d3d4 100644 --- a/src/evaluator/matchers/sw.ts +++ b/src/evaluator/matchers/sw.ts @@ -1,8 +1,9 @@ -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; import { startsWith } from '../../utils/lang'; -export default function startsWithMatcherContext(ruleAttr: string[]) /*: Function */ { +export default function startsWithMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function startsWithMatcher(runtimeAttr: string): boolean { let matches = ruleAttr.some(e => startsWith(runtimeAttr, e)); diff --git a/src/evaluator/matchers/whitelist.ts b/src/evaluator/matchers/whitelist.ts index de72a3a1..0707580f 100644 --- a/src/evaluator/matchers/whitelist.ts +++ b/src/evaluator/matchers/whitelist.ts @@ -1,8 +1,9 @@ import { setToArray, ISet } from '../../utils/lang/sets'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:matcher'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:matcher'); +import { ILogger } from '../../logger/types'; -export default function whitelistMatcherContext(ruleAttr: ISet) /*: Function */ { +export default function whitelistMatcherContext(log: ILogger, ruleAttr: ISet) /*: Function */ { return function whitelistMatcher(runtimeAttr: string): boolean { let isInWhitelist = ruleAttr.has(runtimeAttr); diff --git a/src/evaluator/parser/__tests__/boolean.spec.ts b/src/evaluator/parser/__tests__/boolean.spec.ts index 464e6525..116c3f70 100644 --- a/src/evaluator/parser/__tests__/boolean.spec.ts +++ b/src/evaluator/parser/__tests__/boolean.spec.ts @@ -2,11 +2,12 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; import { IEvaluation } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('PARSER / if user.boolean is true then split 100%:on', async function () { // @ts-ignore - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/index.spec.ts b/src/evaluator/parser/__tests__/index.spec.ts index 32414290..d2e218d1 100644 --- a/src/evaluator/parser/__tests__/index.spec.ts +++ b/src/evaluator/parser/__tests__/index.spec.ts @@ -3,10 +3,11 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; import { bucket } from '../../../utils/murmur3/murmur3'; +import { noopLogger } from '../../../logger/noopLogger'; test('PARSER / if user is in segment all 100%:on', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -32,7 +33,7 @@ test('PARSER / if user is in segment all 100%:on', async function () { test('PARSER / if user is in segment all 100%:off', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -60,7 +61,7 @@ test('PARSER / if user is in segment all 100%:off', async function () { test('PARSER / NEGATED if user is in segment all 100%:on, then no match', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -85,7 +86,7 @@ test('PARSER / NEGATED if user is in segment all 100%:on, then no match', async test('PARSER / if user is in segment ["u1", "u2", "u3", "u4"] then split 100%:on', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -124,7 +125,7 @@ test('PARSER / if user is in segment ["u1", "u2", "u3", "u4"] then split 100%:on test('PARSER / NEGATED if user is in segment ["u1", "u2", "u3", "u4"] then split 100%:on, negated results', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -163,7 +164,7 @@ test('PARSER / NEGATED if user is in segment ["u1", "u2", "u3", "u4"] then split test('PARSER / if user.account is in list ["v1", "v2", "v3"] then split 100:on', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -209,7 +210,7 @@ test('PARSER / if user.account is in list ["v1", "v2", "v3"] then split 100:on', test('PARSER / NEGATED if user.account is in list ["v1", "v2", "v3"] then split 100:on, negated results', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -255,7 +256,7 @@ test('PARSER / NEGATED if user.account is in list ["v1", "v2", "v3"] then split }); test('PARSER / if user.account is in segment all then split 100:on', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -281,7 +282,7 @@ test('PARSER / if user.account is in segment all then split 100:on', async funct test('PARSER / if user.attr is between 10 and 20 then split 100:on', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -322,7 +323,7 @@ test('PARSER / if user.attr is between 10 and 20 then split 100:on', async funct test('PARSER / NEGATED if user.attr is between 10 and 20 then split 100:on, negated results', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -364,7 +365,7 @@ test('PARSER / NEGATED if user.attr is between 10 and 20 then split 100:on, nega test('PARSER / if user.attr <= datetime 1458240947021 then split 100:on', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -409,7 +410,7 @@ test('PARSER / if user.attr <= datetime 1458240947021 then split 100:on', async test('PARSER / NEGATED if user.attr <= datetime 1458240947021 then split 100:on, negated results', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -455,7 +456,7 @@ test('PARSER / NEGATED if user.attr <= datetime 1458240947021 then split 100:on, test('PARSER / if user.attr >= datetime 1458240947021 then split 100:on', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -500,7 +501,7 @@ test('PARSER / if user.attr >= datetime 1458240947021 then split 100:on', async test('PARSER / NEGATED if user.attr >= datetime 1458240947021 then split 100:on, negated results', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -546,7 +547,7 @@ test('PARSER / NEGATED if user.attr >= datetime 1458240947021 then split 100:on, test('PARSER / if user.attr = datetime 1458240947021 then split 100:on', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -591,7 +592,7 @@ test('PARSER / if user.attr = datetime 1458240947021 then split 100:on', async f test('PARSER / NEGATED if user.attr = datetime 1458240947021 then split 100:on, negated results', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -636,7 +637,7 @@ test('PARSER / NEGATED if user.attr = datetime 1458240947021 then split 100:on, }); test('PARSER / if user is in segment all then split 20%:A,20%:B,60%:A', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/invalidMatcher.spec.ts b/src/evaluator/parser/__tests__/invalidMatcher.spec.ts index d140aea9..0f724461 100644 --- a/src/evaluator/parser/__tests__/invalidMatcher.spec.ts +++ b/src/evaluator/parser/__tests__/invalidMatcher.spec.ts @@ -1,9 +1,10 @@ // @ts-nocheck import parser from '..'; import { ISplitCondition } from '../../../dtos/types'; +import { noopLogger } from '../../../logger/noopLogger'; test('PARSER / handle invalid matcher as control', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -32,7 +33,7 @@ test('PARSER / handle invalid matcher as control', async function () { }); test('PARSER / handle invalid matcher as control (complex example)', async function () { - const evaluator = parser([ + const evaluator = parser(noopLogger, [ { 'conditionType': 'WHITELIST', 'matcherGroup': { @@ -132,7 +133,7 @@ test('PARSER / handle invalid matcher as control (complex example)', async funct }); test('PARSER / handle invalid matcher as control (complex example mixing invalid and valid matchers)', async function () { - const evaluator = parser([ + const evaluator = parser(noopLogger, [ { 'conditionType': 'WHITELIST', 'matcherGroup': { diff --git a/src/evaluator/parser/__tests__/regex.spec.ts b/src/evaluator/parser/__tests__/regex.spec.ts index 0c83f0a0..a724f1bf 100644 --- a/src/evaluator/parser/__tests__/regex.spec.ts +++ b/src/evaluator/parser/__tests__/regex.spec.ts @@ -2,10 +2,11 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; import { IEvaluation } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('PARSER / if user.string is true then split 100%:on', async function () { // @ts-ignore - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/set.spec.ts b/src/evaluator/parser/__tests__/set.spec.ts index f46e1c0a..2200a92f 100644 --- a/src/evaluator/parser/__tests__/set.spec.ts +++ b/src/evaluator/parser/__tests__/set.spec.ts @@ -2,13 +2,14 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; +import { noopLogger } from '../../../logger/noopLogger'; // // EQUAL_TO_SET // test('PARSER / if user.permissions ["read", "write"] equal to set ["read", "write"] then split 100:on', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -43,7 +44,7 @@ test('PARSER / if user.permissions ["read", "write"] equal to set ["read", "writ test('PARSER / if user.permissions ["write", "read"] equal to set ["read", "write"] then split 100:on', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -78,7 +79,7 @@ test('PARSER / if user.permissions ["write", "read"] equal to set ["read", "writ test('PARSER / if user.permissions ["1", 2] equal to set ["1", "2"] then split 100:on', async function () { const label = 'permissions = ["1", "2"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -113,7 +114,7 @@ test('PARSER / if user.permissions ["1", 2] equal to set ["1", "2"] then split 1 test('PARSER / if user.permissions ["read", "write", "delete"] equal to set ["read", "write"] then not match', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -147,7 +148,7 @@ test('PARSER / if user.permissions ["read", "write", "delete"] equal to set ["re test('PARSER / if user.permissions ["read"] equal to set ["read", "write"] then not match', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -181,7 +182,7 @@ test('PARSER / if user.permissions ["read"] equal to set ["read", "write"] then test('PARSER / if user.permissions ["read", "delete"] equal to set ["read", "write"] then not match', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -215,7 +216,7 @@ test('PARSER / if user.permissions ["read", "delete"] equal to set ["read", "wri test('PARSER / if user.countries ["argentina", "usa"] equal to set ["usa","argentina"] then split 100:on', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -249,7 +250,7 @@ test('PARSER / if user.countries ["argentina", "usa"] equal to set ["usa","argen test('PARSER / if attribute is not an array we should not match equal to set', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -284,7 +285,7 @@ test('PARSER / if attribute is not an array we should not match equal to set', a test('PARSER / if attribute is an EMPTY array we should not match equal to set', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -317,7 +318,7 @@ test('PARSER / if attribute is an EMPTY array we should not match equal to set', test('PARSER / NEGATED if user.permissions ["read", "write"] equal to set ["read", "write"] then split 100:on should not match', async function () { const label = 'not permissions = ["read", "write"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -350,7 +351,7 @@ test('PARSER / NEGATED if user.permissions ["read", "write"] equal to set ["read test('PARSER / NEGATED if user.permissions ["read"] equal to set ["read", "write"] false, then match', async function () { const label = 'not permissions = ["read", "write"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -384,7 +385,7 @@ test('PARSER / NEGATED if user.permissions ["read"] equal to set ["read", "write test('PARSER / NEGATED if attribute is not an array we should not match equal to set, so match', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -421,7 +422,7 @@ test('PARSER / NEGATED if attribute is not an array we should not match equal to test('PARSER / NEGATED if attribute is an EMPTY array we should not match equal to set, so match', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -458,7 +459,7 @@ test('PARSER / NEGATED if attribute is an EMPTY array we should not match equal // test('PARSER / if user.permissions ["read", "edit", "delete"] contains all of set ["read", "edit"] then split 100:on', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -493,7 +494,7 @@ test('PARSER / if user.permissions ["read", "edit", "delete"] contains all of se test('PARSER / if user.permissions ["edit", "read", "delete"] contains all of set ["read", "edit"] then split 100:on', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -528,7 +529,7 @@ test('PARSER / if user.permissions ["edit", "read", "delete"] contains all of se test('PARSER / if user.permissions [1, "edit", "delete"] contains all of set ["1", "edit"] then split 100:on', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -563,7 +564,7 @@ test('PARSER / if user.permissions [1, "edit", "delete"] contains all of set ["1 test('PARSER / if user.permissions ["read"] contains all of set ["read", "edit"] then not match', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -597,7 +598,7 @@ test('PARSER / if user.permissions ["read"] contains all of set ["read", "edit"] test('PARSER / if user.permissions ["read", "delete", "manage"] contains all of set ["read", "edit"] then not match', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -631,7 +632,7 @@ test('PARSER / if user.permissions ["read", "delete", "manage"] contains all of test('PARSER / if attribute is not an array we should not match contains all', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -666,7 +667,7 @@ test('PARSER / if attribute is not an array we should not match contains all', a test('PARSER / if attribute is an EMPTY array we should not match contains all', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -699,7 +700,7 @@ test('PARSER / if attribute is an EMPTY array we should not match contains all', test('PARSER / NEGATED if user.permissions ["read", "edit", "delete"] contains all of set ["read", "edit"] then split 100:on should not match', async function () { const label = 'not permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -732,7 +733,7 @@ test('PARSER / NEGATED if user.permissions ["read", "edit", "delete"] contains a test('PARSER / NEGATED if user.permissions ["read"] contains all of set ["read", "edit"] false, so match', async function () { const label = 'not permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -766,7 +767,7 @@ test('PARSER / NEGATED if user.permissions ["read"] contains all of set ["read", test('PARSER / NEGATED if attribute is not an array we should not match contains all, so match', async function () { const label = 'not permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -803,7 +804,7 @@ test('PARSER / NEGATED if attribute is not an array we should not match contains test('PARSER / NEGATED if attribute is an EMPTY array we should not match contains all, so match', async function () { const label = 'not permissions contains ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -840,7 +841,7 @@ test('PARSER / NEGATED if attribute is an EMPTY array we should not match contai // test('PARSER / if user.permissions ["read", "edit"] is part of set ["read", "edit", "delete"] then split 100:on', async function () { const label = 'permissions part of ["read", "edit", "delete"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -875,7 +876,7 @@ test('PARSER / if user.permissions ["read", "edit"] is part of set ["read", "edi test('PARSER / if user.permissions ["edit", "read"] is part of set ["read", "edit", "delete"] then split 100:on', async function () { const label = 'permissions part of ["read", "edit", "delete"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -910,7 +911,7 @@ test('PARSER / if user.permissions ["edit", "read"] is part of set ["read", "edi test('PARSER / if user.permissions [1, "edit"] is part of set ["1", "edit", "delete"] then split 100:on', async function () { const label = 'permissions part of ["1", "edit", "delete"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -945,7 +946,7 @@ test('PARSER / if user.permissions [1, "edit"] is part of set ["1", "edit", "del test('PARSER / if user.permissions ["admin", "magic"] is part of set ["read", "edit"] then not match', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -979,7 +980,7 @@ test('PARSER / if user.permissions ["admin", "magic"] is part of set ["read", "e test('PARSER / if attribute is not an array we should not match part of', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1014,7 +1015,7 @@ test('PARSER / if attribute is not an array we should not match part of', async test('PARSER / if attribute is an EMPTY array we should not match part of', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1047,7 +1048,7 @@ test('PARSER / if attribute is an EMPTY array we should not match part of', asyn test('PARSER / NEGATED if user.permissions ["read", "edit"] is part of set ["read", "edit", "delete"] then split 100:on should not match', async function () { const label = 'not permissions part of ["read", "edit", "delete"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1080,7 +1081,7 @@ test('PARSER / NEGATED if user.permissions ["read", "edit"] is part of set ["rea test('PARSER / NEGATED if user.permissions ["admin", "magic"] is part of set ["read", "edit"] false, then match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1114,7 +1115,7 @@ test('PARSER / NEGATED if user.permissions ["admin", "magic"] is part of set ["r test('PARSER / NEGATED if attribute is not an array we should not match part of, so match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1151,7 +1152,7 @@ test('PARSER / NEGATED if attribute is not an array we should not match part of, test('PARSER / NEGATED if attribute is an EMPTY array we should not match part of, so match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1188,7 +1189,7 @@ test('PARSER / NEGATED if attribute is an EMPTY array we should not match part o // test('PARSER / if user.permissions ["admin", "edit"] contains any of set ["read", "edit", "delete"] then split 100:on', async function () { const label = 'permissions part of ["read", "edit", "delete"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1223,7 +1224,7 @@ test('PARSER / if user.permissions ["admin", "edit"] contains any of set ["read" test('PARSER / if user.permissions ["admin", 1] contains any of set ["read", "1", "delete"] then split 100:on', async function () { const label = 'permissions part of ["read", "1", "delete"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1258,7 +1259,7 @@ test('PARSER / if user.permissions ["admin", 1] contains any of set ["read", "1" test('PARSER / if user.permissions ["admin", "magic"] contains any of set ["read", "edit"] then not match', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1292,7 +1293,7 @@ test('PARSER / if user.permissions ["admin", "magic"] contains any of set ["read test('PARSER / if attribute is not an array we should not match contains any', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1327,7 +1328,7 @@ test('PARSER / if attribute is not an array we should not match contains any', a test('PARSER / if attribute is an EMPTY array we should not match contains any', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1360,7 +1361,7 @@ test('PARSER / if attribute is an EMPTY array we should not match contains any', test('PARSER / NEGATED if user.permissions ["admin", "edit"] contains any of set ["read", "edit", "delete"] then split 100:on should not match', async function () { const label = 'not permissions part of ["read", "edit", "delete"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1393,7 +1394,7 @@ test('PARSER / NEGATED if user.permissions ["admin", "edit"] contains any of set test('PARSER / NEGATED if user.permissions ["admin", "magic"] contains any of set ["read", "edit"] false, then should match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1427,7 +1428,7 @@ test('PARSER / NEGATED if user.permissions ["admin", "magic"] contains any of se test('PARSER / NEGATED if attribute is not an array we should not match contains any, then should match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1459,7 +1460,7 @@ test('PARSER / NEGATED if attribute is not an array we should not match contains test('PARSER / NEGATED if attribute is an EMPTY array we should not match contains any, then should match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/string.spec.ts b/src/evaluator/parser/__tests__/string.spec.ts index 10304629..d40c7f7e 100644 --- a/src/evaluator/parser/__tests__/string.spec.ts +++ b/src/evaluator/parser/__tests__/string.spec.ts @@ -2,13 +2,14 @@ import parser from '..'; import { ISplitCondition } from '../../../dtos/types'; import { keyParser } from '../../../utils/key'; +import { noopLogger } from '../../../logger/noopLogger'; // // STARTS WITH // test('PARSER / if user.email starts with ["nico"] then split 100:on', async function () { const label = 'email starts with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -42,7 +43,7 @@ test('PARSER / if user.email starts with ["nico"] then split 100:on', async func test('PARSER / if user.email = 123, starts with ["1"] then split 100:on should match', async function () { const label = 'email starts with ["1"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -76,7 +77,7 @@ test('PARSER / if user.email = 123, starts with ["1"] then split 100:on should m test('PARSER / if user.email starts with ["nico", "marcio", "facu"] then split 100:on', async function () { const label = 'email starts with ["nico", "marcio", "facu"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -110,7 +111,7 @@ test('PARSER / if user.email starts with ["nico", "marcio", "facu"] then split 1 test('PARSER / if user.email starts with ["nico", "marcio", "facu"] then split 100:on', async function () { const label = 'email starts with ["nico", "marcio", "facu"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -144,7 +145,7 @@ test('PARSER / if user.email starts with ["nico", "marcio", "facu"] then split 1 test('PARSER / if user.email does not start with ["nico"] then not match', async function () { // const label = 'email starts with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -176,7 +177,7 @@ test('PARSER / if user.email does not start with ["nico"] then not match', async test('PARSER / if user.email is an EMPTY string, start with ["nico"] should not match', async function () { // const label = 'email starts with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -206,7 +207,7 @@ test('PARSER / if user.email is an EMPTY string, start with ["nico"] should not test('PARSER / if user.email is not a string, start with ["nico"] should not match', async function () { // const label = 'email starts with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -239,7 +240,7 @@ test('PARSER / if user.email is not a string, start with ["nico"] should not mat test('PARSER / NEGATED if user.email starts with ["nico"] then split 100:on, so not match', async function () { const label = 'not email starts with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -272,7 +273,7 @@ test('PARSER / NEGATED if user.email starts with ["nico"] then split 100:on, so test('PARSER / NEGATED if user.email does not start with ["nico"] should not match, then match', async function () { const label = 'not email starts with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -306,7 +307,7 @@ test('PARSER / NEGATED if user.email does not start with ["nico"] should not mat test('PARSER / NEGATED if user.email is an EMPTY string, start with ["nico"] should not match, so negation should', async function () { const label = 'not email starts with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -338,7 +339,7 @@ test('PARSER / NEGATED if user.email is an EMPTY string, start with ["nico"] sho test('PARSER / NEGATED if user.email is not a string, start with ["nico"] should not match, so negation should', async function () { const label = 'not email starts with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -377,7 +378,7 @@ test('PARSER / NEGATED if user.email is not a string, start with ["nico"] should // test('PARSER / if user.email ends with ["split.io"] then split 100:on', async function () { const label = 'email ends with ["split.io"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -411,7 +412,7 @@ test('PARSER / if user.email ends with ["split.io"] then split 100:on', async fu test('PARSER / if user.email = 123, ends with ["3"] then split 100:on should match', async function () { const label = 'email starts with ["3"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -444,7 +445,7 @@ test('PARSER / if user.email = 123, ends with ["3"] then split 100:on should mat test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] then split 100:on', async function () { const label = 'email ends with ["gmail.com", "split.io", "hotmail.com"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -478,7 +479,7 @@ test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] then split 100:on', async function () { const label = 'email ends with ["gmail.com", "split.io", "hotmail.com"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -512,7 +513,7 @@ test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] but attribute is "" then split 100:on', async function () { const label = 'email ends with ["gmail.com", "split.io", "hotmail.com"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -545,7 +546,7 @@ test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] test('PARSER / if user.email does not end with ["split.io"] then not match', async function () { const label = 'email ends with ["split.io"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -578,7 +579,7 @@ test('PARSER / if user.email does not end with ["split.io"] then not match', asy test('PARSER / if user.email is an EMPTY string, end with ["nico"] should not match', async function () { // const label = 'email ends with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -608,7 +609,7 @@ test('PARSER / if user.email is an EMPTY string, end with ["nico"] should not ma test('PARSER / if user.email is not a string, end with ["nico"] should not match', async function () { // const label = 'email ends with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -643,7 +644,7 @@ test('PARSER / if user.email is not a string, end with ["nico"] should not match test('PARSER / NEGATED if user.email ends with ["split.io"] then split 100:on, so not match', async function () { const label = 'not email ends with ["split.io"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -675,7 +676,7 @@ test('PARSER / NEGATED if user.email ends with ["split.io"] then split 100:on, s test('PARSER / NEGATED if user.email does not end with ["split.io"] then no match, so match', async function () { const label = 'not email ends with ["split.io"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -708,7 +709,7 @@ test('PARSER / NEGATED if user.email does not end with ["split.io"] then no matc test('PARSER / NEGATED if user.email is an EMPTY string, end with ["nico"] should not match, so negation should', async function () { const label = 'not email ends with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -740,7 +741,7 @@ test('PARSER / NEGATED if user.email is an EMPTY string, end with ["nico"] shoul test('PARSER / NEGATED if user.email is not a string, end with ["nico"] should not match, so negation should', async function () { const label = 'not email ends with ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -779,7 +780,7 @@ test('PARSER / NEGATED if user.email is not a string, end with ["nico"] should n // test('PARSER / if user.email contains ["@split"] then split 100:on', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -813,7 +814,7 @@ test('PARSER / if user.email contains ["@split"] then split 100:on', async funct test('PARSER / if user.email = 123, contains ["2"] then split 100:on should match', async function () { const label = 'email contains ["2"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -847,7 +848,7 @@ test('PARSER / if user.email = 123, contains ["2"] then split 100:on should matc test('PARSER / if user.email contains ["@split"] (beginning) then split 100:on', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -881,7 +882,7 @@ test('PARSER / if user.email contains ["@split"] (beginning) then split 100:on', test('PARSER / if user.email contains ["@split"] (end) then split 100:on', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -915,7 +916,7 @@ test('PARSER / if user.email contains ["@split"] (end) then split 100:on', async test('PARSER / if user.email contains ["@split"] (whole string matches) then split 100:on', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -949,7 +950,7 @@ test('PARSER / if user.email contains ["@split"] (whole string matches) then spl test('PARSER / if user.email contains ["@split", "@gmail", "@hotmail"] then split 100:on', async function () { const label = 'email contains ["@split", "@gmail", "@hotmail"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -983,7 +984,7 @@ test('PARSER / if user.email contains ["@split", "@gmail", "@hotmail"] then spli test('PARSER / if user.email contains ["@split", "@gmail", "@hotmail"] then split 100:on', async function () { const label = 'email contains ["@split", "@gmail", "@hotmail"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1017,7 +1018,7 @@ test('PARSER / if user.email contains ["@split", "@gmail", "@hotmail"] then spli test('PARSER / if user.email does not contain ["@split"] then not match', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1050,7 +1051,7 @@ test('PARSER / if user.email does not contain ["@split"] then not match', async test('PARSER / if user.email is an EMPTY string, contains ["nico"] should not match', async function () { // const label = 'email contains ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1080,7 +1081,7 @@ test('PARSER / if user.email is an EMPTY string, contains ["nico"] should not ma test('PARSER / if user.email is not a string, contains ["nico"] should not match', async function () { // const label = 'email contains ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1115,7 +1116,7 @@ test('PARSER / if user.email is not a string, contains ["nico"] should not match test('PARSER / NEGATED if user.email contains ["@split"] then split 100:on, then no match', async function () { const label = 'not email contains ["@split"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1148,7 +1149,7 @@ test('PARSER / NEGATED if user.email contains ["@split"] then split 100:on, then test('PARSER / NEGATED if user.email does not contain ["@split"] then not match, so match', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1181,7 +1182,7 @@ test('PARSER / NEGATED if user.email does not contain ["@split"] then not match, test('PARSER / NEGATED if user.email is an EMPTY string, contains ["nico"] should not match, so negation should', async function () { const label = 'not email contains ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1213,7 +1214,7 @@ test('PARSER / NEGATED if user.email is an EMPTY string, contains ["nico"] shoul test('PARSER / NEGATED if user.email is not a string, contains ["nico"] should not match, so negation should', async function () { const label = 'not email contains ["nico"]'; - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/trafficAllocation.spec.ts b/src/evaluator/parser/__tests__/trafficAllocation.spec.ts index e2bd4ece..fec085f3 100644 --- a/src/evaluator/parser/__tests__/trafficAllocation.spec.ts +++ b/src/evaluator/parser/__tests__/trafficAllocation.spec.ts @@ -1,11 +1,13 @@ +// @ts-nocheck import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; import { IEvaluation } from '../../types'; +import { noopLogger } from '../../../logger/noopLogger'; test('PARSER / if user is in segment all 100%:on but trafficAllocation is 0%', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ conditionType: 'ROLLOUT', matcherGroup: { combiner: 'AND', @@ -32,7 +34,7 @@ test('PARSER / if user is in segment all 100%:on but trafficAllocation is 0%', a test('PARSER / if user is in segment all 100%:on but trafficAllocation is 99% with bucket below 99', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ conditionType: 'ROLLOUT', matcherGroup: { combiner: 'AND', @@ -59,7 +61,7 @@ test('PARSER / if user is in segment all 100%:on but trafficAllocation is 99% wi test('PARSER / if user is in segment all 100%:on but trafficAllocation is 99% and bucket returns 100', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ conditionType: 'ROLLOUT', matcherGroup: { combiner: 'AND', @@ -86,7 +88,7 @@ test('PARSER / if user is in segment all 100%:on but trafficAllocation is 99% an test('PARSER / if user is whitelisted and in segment all 100%:off with trafficAllocation as 0%', async function () { - const evaluator = parser([{ + const evaluator = parser(noopLogger, [{ conditionType: 'WHITELIST', matcherGroup: { combiner: 'AND', diff --git a/src/evaluator/parser/index.ts b/src/evaluator/parser/index.ts index cd290cfb..41a03867 100644 --- a/src/evaluator/parser/index.ts +++ b/src/evaluator/parser/index.ts @@ -10,8 +10,9 @@ import { IEvaluator, IMatcherDto, ISplitEvaluator } from '../types'; import { ISplitCondition } from '../../dtos/types'; import { IStorageAsync, IStorageSync } from '../../storages/types'; import { SplitIO } from '../../types'; +import { ILogger } from '../../logger/types'; -export default function parser(conditions: ISplitCondition[], storage?: IStorageSync | IStorageAsync): IEvaluator { +export default function parser(log: ILogger, conditions: ISplitCondition[], storage: IStorageSync | IStorageAsync): IEvaluator { let predicates = []; for (let i = 0; i < conditions.length; i++) { @@ -27,11 +28,11 @@ export default function parser(conditions: ISplitCondition[], storage?: IStorage // create a set of pure functions from the matcher's dto const expressions = matchers.map((matcherDto: IMatcherDto) => { - const matcher = matcherFactory(matcherDto, storage); + const matcher = matcherFactory(log, matcherDto, storage); // Evaluator function. return (key: string, attributes: SplitIO.Attributes, splitEvaluator: ISplitEvaluator) => { - const value = sanitizeValue(key, matcherDto, attributes); + const value = sanitizeValue(key, matcherDto, attributes, log); const result = value !== undefined && matcher ? matcher(value, splitEvaluator) : false; if (thenable(result)) { @@ -53,7 +54,7 @@ export default function parser(conditions: ISplitCondition[], storage?: IStorage } predicates.push(conditionFactory( - andCombiner(expressions), + andCombiner(expressions, log), Treatments.parse(partitions), label, conditionType @@ -61,5 +62,5 @@ export default function parser(conditions: ISplitCondition[], storage?: IStorage } // Instanciate evaluator given the set of conditions using if else if logic - return ifElseIfCombiner(predicates); + return ifElseIfCombiner(predicates, log); } diff --git a/src/evaluator/types.ts b/src/evaluator/types.ts index bda369e0..3befebeb 100644 --- a/src/evaluator/types.ts +++ b/src/evaluator/types.ts @@ -2,6 +2,7 @@ import { IBetweenMatcherData, IDependencyMatcherData, MaybeThenable } from '../d import { IStorageAsync, IStorageSync } from '../storages/types'; import { ISet } from '../utils/lang/sets'; import { SplitIO } from '../types'; +import { ILogger } from '../logger/types'; export interface IDependencyMatcherValue { key: SplitIO.SplitKey, @@ -26,7 +27,7 @@ export interface IEvaluation { export type IEvaluationResult = IEvaluation & { treatment: string } -export type ISplitEvaluator = (key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes, storage: IStorageSync | IStorageAsync) => MaybeThenable +export type ISplitEvaluator = (key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes, storage: IStorageSync | IStorageAsync, log: ILogger) => MaybeThenable export type IEvaluator = (key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index d3ccdded..fd50b791 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -1,10 +1,11 @@ import { SplitIO } from '../../types'; -import { logFactory } from '../../logger/sdkLogger'; import { IMatcherDto } from '../types'; -const log = logFactory('splitio-engine:value'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:value'); +import { ILogger } from '../../logger/types'; import sanitizeValue from './sanitize'; -function parseValue(key: string, attributeName: string | null, attributes: SplitIO.Attributes) { +function parseValue(key: string, attributeName: string | null, attributes: SplitIO.Attributes, log: ILogger) { let value = undefined; if (attributeName) { if (attributes) { @@ -23,10 +24,10 @@ function parseValue(key: string, attributeName: string | null, attributes: Split /** * Defines value to be matched (key / attribute). */ -export default function value(key: string, matcherDto: IMatcherDto, attributes: SplitIO.Attributes) { +export default function value(key: string, matcherDto: IMatcherDto, attributes: SplitIO.Attributes, log: ILogger) { const attributeName = matcherDto.attribute; - const valueToMatch = parseValue(key, attributeName, attributes); - const sanitizedValue = sanitizeValue(matcherDto.type, valueToMatch, matcherDto.dataType, attributes); + const valueToMatch = parseValue(key, attributeName, attributes, log); + const sanitizedValue = sanitizeValue(matcherDto.type, valueToMatch, matcherDto.dataType, attributes, log); if (sanitizedValue !== undefined) { return sanitizedValue; diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index ff014fd1..b47f5ef4 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -1,7 +1,8 @@ import { SplitIO } from '../../types'; import { IDependencyMatcherValue } from '../types'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-engine:sanitize'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-engine:sanitize'); +import { ILogger } from '../../logger/types'; import { isObject, uniq, toString, toNumber } from '../../utils/lang'; import { zeroSinceHH, zeroSinceSS } from '../convertions'; import { matcherTypes, dataTypes } from '../matchers/matcherTypes'; @@ -69,7 +70,7 @@ function getProcessingFunction(matcherTypeID: number, dataType: string) { /** * Sanitize matcher value */ -export default function sanitize(matcherTypeID: number, value: string | number | boolean | Array | undefined, dataType: string, attributes: SplitIO.Attributes) { +export default function sanitize(matcherTypeID: number, value: string | number | boolean | Array | undefined, dataType: string, attributes: SplitIO.Attributes, log: ILogger) { const processor = getProcessingFunction(matcherTypeID, dataType); let sanitizedValue: string | number | boolean | Array | IDependencyMatcherValue | undefined; diff --git a/src/logger/index.ts b/src/logger/index.ts index 166b9159..3078422f 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -1,5 +1,5 @@ import objectAssign from 'object-assign'; -import { ILoggerOptions } from './types'; +import { ILoggerOptions, ILogger } from './types'; import { find } from '../utils/lang'; import { LogLevel } from '../types'; @@ -27,7 +27,7 @@ const defaultOptions = { displayAllErrors: false }; -export class Logger { +export class Logger implements ILogger { private category: any; private options: any; diff --git a/src/logger/noopLogger.ts b/src/logger/noopLogger.ts new file mode 100644 index 00000000..36d77895 --- /dev/null +++ b/src/logger/noopLogger.ts @@ -0,0 +1,8 @@ +import { ILogger } from './types'; + +export const noopLogger: ILogger = { + d() {}, + i() {}, + w() {}, + e() {}, +}; diff --git a/src/logger/types.ts b/src/logger/types.ts index 3ef2b261..0ffd499b 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -2,3 +2,13 @@ export interface ILoggerOptions { showLevel?: boolean, displayAllErrors?: boolean } + +export interface ILogger { + d(msg: string): void + + i(msg: string): void + + w(msg: string): void + + e(msg: string): void +} diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index e3aed544..b8b095ce 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -27,7 +27,7 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl return treatment; }; - const evaluation = evaluateFeature(key, splitName, attributes, storage); + const evaluation = evaluateFeature(key, splitName, attributes, storage, log); return thenable(evaluation) ? evaluation.then((res) => wrapUp(res)) : wrapUp(evaluation); } @@ -47,7 +47,7 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl return treatments; }; - const evaluations = evaluateFeatures(key, splitNames, attributes, storage); + const evaluations = evaluateFeatures(key, splitNames, attributes, storage, log); return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations); } From cfead7ec925860cb72969b589346d3d161d1a702 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 25 Feb 2021 14:32:42 -0300 Subject: [PATCH 03/58] added support for message codes --- src/evaluator/matchers/dependency.ts | 2 +- src/evaluator/value/index.ts | 2 +- src/logger/__tests__/index.spec.ts | 12 ++++---- src/logger/codes.ts | 9 ++++++ src/logger/index.ts | 43 +++++++++++++++++----------- src/logger/sdkLogger.ts | 3 +- src/logger/types.ts | 12 +++++--- src/services/splitApi.ts | 6 ++-- src/services/splitHttpClient.ts | 4 +-- src/services/types.ts | 2 +- src/sync/streaming/pushManager.ts | 2 +- src/sync/streaming/pushManagerCS.ts | 2 +- src/sync/streaming/pushManagerSS.ts | 2 +- src/utils/timeTracker/index.ts | 3 +- 14 files changed, 66 insertions(+), 38 deletions(-) create mode 100644 src/logger/codes.ts diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index ba95c965..db1dae54 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -21,7 +21,7 @@ export default function dependencyMatcherContext(log: ILogger, { split, treatmen } return function dependencyMatcher({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator): MaybeThenable { - log.d(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? `\n attributes: ${JSON.stringify(attributes)}` : ''}`); + log.d(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? '\n attributes: ' + JSON.stringify(attributes) : ''}`); const evaluation = splitEvaluator(key, split, attributes, storage, log); if (thenable(evaluation)) { diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index fd50b791..3897ae6b 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -32,7 +32,7 @@ export default function value(key: string, matcherDto: IMatcherDto, attributes: if (sanitizedValue !== undefined) { return sanitizedValue; } else { - log.w(`Value ${valueToMatch} ${attributeName ? `for attribute ${attributeName} ` : + ''}doesn't match with expected type.`); + log.w(`Value ${valueToMatch} ${attributeName ? ' for attribute ' + attributeName : ''}doesn't match with expected type.`); return; } } diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index cc01c897..e820dee8 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -1,4 +1,6 @@ import { Logger, LogLevels, setLogLevel, isLogLevelString } from '../index'; +import { codes } from '../codes'; +import { LogLevel } from '../../types'; // We'll set this only once. These are the constants we will use for // comparing the LogLevel values. @@ -32,7 +34,7 @@ test('SPLIT LOGGER / LogLevels exposed mappings', () => { test('SPLIT LOGGER / Logger class shape', () => { expect(typeof Logger).toBe('function'); // Logger should be a class we can instantiate. - const logger = new Logger('test-category', {}); + const logger = new Logger('test-category', {}, codes); expect(typeof logger.d).toBe('function'); // instance.d should be a method. expect(typeof logger.i).toBe('function'); // instance.i should be a method. @@ -41,9 +43,9 @@ test('SPLIT LOGGER / Logger class shape', () => { }); -const LOG_LEVELS_IN_ORDER = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE']; +const LOG_LEVELS_IN_ORDER: LogLevel[] = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE']; /* Utility function to avoid repeating too much code */ -function testLogLevels(levelToTest: string) { +function testLogLevels(levelToTest: LogLevel) { // Builds the expected message. const buildExpectedMessage = (lvl: string, category: string, msg: string, showLevel?: boolean) => { let res = ''; @@ -64,9 +66,9 @@ function testLogLevels(levelToTest: string) { const logCategory = `test-category-${logMethod}${displayAllErrors ? 'displayAllErrors' : ''}`; const instance = new Logger(logCategory, { showLevel, displayAllErrors - }); + }, codes); - LOG_LEVELS_IN_ORDER.forEach((logLevel, i) => { + LOG_LEVELS_IN_ORDER.forEach((logLevel: LogLevel, i) => { const logMsg = `Test log for level ${levelToTest} (${displayAllErrors ? 'But all errors are configured to display' : 'Errors not forced to display'}) with showLevel: ${showLevel} ${logLevelLogsCounter}`; const expectedMessage = buildExpectedMessage(levelToTest, logCategory, logMsg, showLevel); diff --git a/src/logger/codes.ts b/src/logger/codes.ts new file mode 100644 index 00000000..bba7665d --- /dev/null +++ b/src/logger/codes.ts @@ -0,0 +1,9 @@ +import { ICodes } from './types'; + +export const codes: ICodes = { + DEBUG: [], + ERROR: [], + INFO: [], + WARN: [], + NONE: [], +}; diff --git a/src/logger/index.ts b/src/logger/index.ts index 3078422f..27cc1d87 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -1,9 +1,9 @@ import objectAssign from 'object-assign'; -import { ILoggerOptions, ILogger } from './types'; +import { ILoggerOptions, ILogger, ICodes } from './types'; import { find } from '../utils/lang'; import { LogLevel } from '../types'; -export const LogLevels: { [level: string]: LogLevel } = { +export const LogLevels: { [level in LogLevel]: LogLevel } = { DEBUG: 'DEBUG', INFO: 'INFO', WARN: 'WARN', @@ -22,47 +22,58 @@ export function isLogLevelString(str: string): str is LogLevel { return !!find(LogLevels, (lvl: string) => str === lvl); } +function sprintf(format: string = '', args: any[] = []): string { + var i = 0; + return format.replace(/%s/g, function () { + return args[i++]; + }); +} + const defaultOptions = { showLevel: true, displayAllErrors: false }; export class Logger implements ILogger { - private category: any; - private options: any; - constructor(category: string, options: ILoggerOptions) { + private category: string; + private options: ILoggerOptions; + private codes: ICodes; + + constructor(category: string, options: ILoggerOptions, codes: ICodes) { this.category = category; this.options = objectAssign({}, defaultOptions, options); + this.codes = codes; } - d(msg: string) { + d(msg: string | number, args?: any[]) { if (this._shouldLog(LogLevels.DEBUG)) - this._log(LogLevels.DEBUG, msg); + this._log(LogLevels.DEBUG, msg, args); } - i(msg: string) { + i(msg: string | number, args?: any[]) { if (this._shouldLog(LogLevels.INFO)) - this._log(LogLevels.INFO, msg); + this._log(LogLevels.INFO, msg, args); } - w(msg: string) { + w(msg: string | number, args?: any[]) { if (this._shouldLog(LogLevels.WARN)) - this._log(LogLevels.WARN, msg); + this._log(LogLevels.WARN, msg, args); } - e(msg: string) { + e(msg: string | number, args?: any[]) { if (this.options.displayAllErrors || this._shouldLog(LogLevels.ERROR)) - this._log(LogLevels.ERROR, msg); + this._log(LogLevels.ERROR, msg, args); } - _log(level: string, text: string) { + private _log(level: LogLevel, text: string | number, args?: any[]) { + if (typeof text === 'number') text = sprintf(this.codes[level][text], args); const formattedText = this._generateLogMessage(level, text); console.log(formattedText); } - _generateLogMessage(level: string, text: string) { + private _generateLogMessage(level: string, text: string) { const textPre = ' => '; let result = ''; @@ -77,7 +88,7 @@ export class Logger implements ILogger { return result += text; } - _shouldLog(level: LogLevel) { + private _shouldLog(level: LogLevel) { const logLevel = globalLogLevel; const levels = Object.keys(LogLevels).map((f) => LogLevels[f as keyof typeof LogLevels]); const index = levels.indexOf(level); // What's the index of what it's trying to check if it should log diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 0e0ab37e..9fd0ae6f 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -7,6 +7,7 @@ import { isLocalStorageAvailable } from '../utils/env/isLocalStorageAvailable'; import { isNode } from '../utils/env/isNode'; import { merge } from '../utils/lang'; import { ILoggerAPI } from '../types'; +import { codes } from './codes'; // @TODO when integrating with other packages, find the best way to update LoggerOption defaults per package (node, evaluator, etc.) const defaultOptions: ILoggerOptions = { @@ -30,7 +31,7 @@ const initialState = String( ); // we expose the logger instance creator -export const logFactory = (namespace: string, options = {}) => new Logger(namespace, merge(options, defaultOptions)); +export const logFactory = (namespace: string, options = {}) => new Logger(namespace, merge(options, defaultOptions), codes); const ownLog = logFactory('splitio-utils:logger'); diff --git a/src/logger/types.ts b/src/logger/types.ts index 0ffd499b..666ad2f3 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -1,14 +1,18 @@ +import { LogLevel } from '../types'; + export interface ILoggerOptions { showLevel?: boolean, displayAllErrors?: boolean } export interface ILogger { - d(msg: string): void + d(msg: string | number, args?: any[]): void - i(msg: string): void + i(msg: string | number, args?: any[]): void - w(msg: string): void + w(msg: string | number, args?: any[]): void - e(msg: string): void + e(msg: string | number, args?: any[]): void } + +export type ICodes = { [level in LogLevel]: string[] } diff --git a/src/services/splitApi.ts b/src/services/splitApi.ts index d5c2b827..befc4af5 100644 --- a/src/services/splitApi.ts +++ b/src/services/splitApi.ts @@ -62,7 +62,7 @@ export function splitApiFactory(settings: ISettings, platform: IPlatform): ISpli postTestImpressionsBulk(body: string) { const url = `${urls.events}/testImpressions/bulk`; - return splitHttpClient(url, 'POST', body, false, { + return splitHttpClient(url, 'POST', body, { // Adding extra headers to send impressions in OPTIMIZED or DEBUG modes. SplitSDKImpressionsMode }); @@ -75,12 +75,12 @@ export function splitApiFactory(settings: ISettings, platform: IPlatform): ISpli postMetricsCounters(body: string) { const url = `${urls.events}/metrics/counters`; - return splitHttpClient(url, 'POST', body, true); + return splitHttpClient(url, 'POST', body); }, postMetricsTimes(body: string) { const url = `${urls.events}/metrics/times`; - return splitHttpClient(url, 'POST', body, true); + return splitHttpClient(url, 'POST', body); } }; } diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index 267d31e0..947f519e 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -33,7 +33,7 @@ export function splitHttpClientFactory(apikey: string, metadata: IMetadata, getF if (metadata.ip) headers['SplitSDKMachineIP'] = metadata.ip; if (metadata.hostname) headers['SplitSDKMachineName'] = metadata.hostname; - return function httpClient(url: string, method: string = 'GET', body?: string, logErrorsAsInfo: boolean = false, extraHeaders?: Record): Promise { + return function httpClient(url: string, method: string = 'GET', body?: string, extraHeaders?: Record): Promise { const rHeaders = extraHeaders ? objectAssign({}, headers, extraHeaders) : headers; const request = objectAssign({ headers: rHeaders, method, body }, options); @@ -62,7 +62,7 @@ export function splitHttpClientFactory(apikey: string, metadata: IMetadata, getF } if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else. - log[logErrorsAsInfo ? 'i' : 'e'](`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); + log.e(`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); } // passes `undefined` as statusCode if not an HTTP error (resp === undefined) diff --git a/src/services/types.ts b/src/services/types.ts index ba134f5d..f2603513 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -8,7 +8,7 @@ export type IFetch = ( } ) => Promise -export type ISplitHttpClient = (url: string, method?: string, body?: string, logErrorsAsInfo?: boolean, extraHeaders?: Record) => Promise +export type ISplitHttpClient = (url: string, method?: string, body?: string, extraHeaders?: Record) => Promise export type IFetchAuth = (userKeys?: string[]) => Promise diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index c7203b41..99d6541e 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -186,7 +186,7 @@ export default function pushManagerFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.e(`Fail to connect to streaming${errorMessage ? ', with error message: "' + errorMessage + '"' : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index bbb6040f..5a549f71 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -181,7 +181,7 @@ export default function pushManagerCSFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.e(`Fail to connect to streaming${errorMessage ? ', with error message: "' + errorMessage + '"' : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index 324f3cde..640eeb11 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -158,7 +158,7 @@ export default function pushManagerSSFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.e(`Fail to connect to streaming${errorMessage ? ', with error message: "' + errorMessage + '"' : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/utils/timeTracker/index.ts b/src/utils/timeTracker/index.ts index f3974bbc..65f748ba 100644 --- a/src/utils/timeTracker/index.ts +++ b/src/utils/timeTracker/index.ts @@ -2,6 +2,7 @@ import { uniqueId } from '../lang'; import { Logger } from '../../logger/index'; import timer from './timer'; import thenable from '../promise/thenable'; +import { codes } from '../../logger/codes'; // Based on ProducerMetricsCollector and ClientCollector classes interface MetricsCollector { @@ -23,7 +24,7 @@ interface MetricsCollector { // logger to be used on this module const logger = new Logger('[TIME TRACKER]', { showLevel: false -}); +}, codes); // Map we will use for storing timers data const timers: Record Date: Thu, 25 Feb 2021 17:51:00 -0300 Subject: [PATCH 04/58] injected logger in all modules --- src/integrations/__tests__/browser.spec.ts | 18 +++++---- src/integrations/ga/GaToSplit.ts | 32 +++++++++------- src/integrations/ga/GaToSplitPlugin.ts | 2 +- src/integrations/ga/SplitToGa.ts | 17 +++++---- src/integrations/ga/SplitToGaPlugin.ts | 7 ++-- .../ga/__tests__/GaToSplit.spec.ts | 28 ++++++++------ .../ga/__tests__/SplitToGa.spec.ts | 38 +++++++++---------- src/listeners/__tests__/node.spec.ts | 12 +++--- src/listeners/browser.ts | 8 ++-- src/listeners/node.ts | 20 +++++----- src/readiness/sdkReadinessManager.ts | 18 +++++---- src/sdkClient/client.ts | 10 ++--- src/sdkClient/clientInputValidation.ts | 25 ++++++------ src/sdkClient/sdkClient.ts | 3 +- src/sdkClient/sdkClientMethod.ts | 6 +-- src/sdkClient/sdkClientMethodCS.ts | 10 ++--- src/sdkClient/sdkClientMethodCSWithTT.ts | 14 +++---- src/sdkFactory/index.ts | 20 +++++----- src/sdkFactory/types.ts | 4 +- src/sdkManager/index.ts | 16 ++++---- src/services/splitApi.ts | 8 ++-- src/services/splitHttpClient.ts | 11 +++--- src/services/types.ts | 2 +- .../inLocalStorage/MySegmentsCacheInLocal.ts | 15 +++++--- .../inLocalStorage/SplitsCacheInLocal.ts | 25 ++++++------ src/storages/inLocalStorage/index.ts | 9 +++-- src/storages/inRedis/EventsCacheInRedis.ts | 9 +++-- src/storages/inRedis/RedisAdapter.ts | 27 +++++++------ src/storages/inRedis/SplitsCacheInRedis.ts | 17 +++++---- src/storages/inRedis/index.ts | 7 ++-- src/storages/types.ts | 4 +- .../splitsParser/splitsParserFromFile.ts | 17 +++++---- .../offline/syncTasks/fromObjectSyncTask.ts | 9 +++-- src/sync/polling/pollingManagerCS.ts | 6 ++- src/sync/polling/pollingManagerSS.ts | 6 ++- .../polling/syncTasks/mySegmentsSyncTask.ts | 15 +++++--- .../polling/syncTasks/segmentsSyncTask.ts | 18 +++++---- src/sync/polling/syncTasks/splitsSyncTask.ts | 16 +++++--- src/sync/streaming/SSEHandler/index.ts | 7 ++-- src/sync/streaming/pushManager.ts | 9 +++-- src/sync/streaming/pushManagerCS.ts | 9 +++-- src/sync/streaming/pushManagerSS.ts | 9 +++-- src/sync/submitters/eventsSyncTask.ts | 8 ++-- .../submitters/impressionCountsSyncTask.ts | 4 +- src/sync/submitters/impressionsSyncTask.ts | 4 +- src/sync/submitters/metricsSyncTask.ts | 7 +++- src/sync/submitters/submitterSyncTask.ts | 8 ++-- src/sync/syncManagerOnline.ts | 12 +++--- src/sync/syncTask.ts | 7 ++-- src/trackers/eventTracker.ts | 6 ++- src/trackers/impressionsTracker.ts | 6 ++- src/types.ts | 4 +- src/utils/inputValidation/apiKey.ts | 17 +++++---- src/utils/inputValidation/attributes.ts | 7 ++-- src/utils/inputValidation/event.ts | 7 ++-- src/utils/inputValidation/eventProperties.ts | 7 ++-- src/utils/inputValidation/eventValue.ts | 7 ++-- src/utils/inputValidation/isOperational.ts | 9 +++-- src/utils/inputValidation/key.ts | 15 ++++---- src/utils/inputValidation/preloadedData.ts | 27 ++++++------- src/utils/inputValidation/split.ts | 8 ++-- src/utils/inputValidation/splitExistance.ts | 7 ++-- src/utils/inputValidation/splits.ts | 9 +++-- src/utils/inputValidation/trafficType.ts | 7 ++-- .../inputValidation/trafficTypeExistance.ts | 13 ++++--- .../__tests__/settings.mocks.ts | 7 +++- .../settingsValidation/impressionsMode.ts | 7 ++-- src/utils/settingsValidation/index.ts | 11 ++++-- .../settingsValidation/integrations/common.ts | 6 +-- src/utils/settingsValidation/splitFilters.ts | 13 ++++--- .../settingsValidation/storage/storageCS.ts | 6 +-- 71 files changed, 465 insertions(+), 354 deletions(-) diff --git a/src/integrations/__tests__/browser.spec.ts b/src/integrations/__tests__/browser.spec.ts index 45b99fe4..9121a4c0 100644 --- a/src/integrations/__tests__/browser.spec.ts +++ b/src/integrations/__tests__/browser.spec.ts @@ -1,6 +1,7 @@ import { GOOGLE_ANALYTICS_TO_SPLIT, SPLIT_TO_GOOGLE_ANALYTICS } from '../../utils/constants/browser'; import { SPLIT_IMPRESSION, SPLIT_EVENT } from '../../utils/constants'; import { IIntegrationManager } from '../types'; +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; // Mock integration modules (GaToSplit and SplitToGa). @@ -17,10 +18,11 @@ const SplitToGaQueueMethod = jest.fn(); }); -const fakeContext = { +const fakeParams = { storage: 'fakeStorage', settings: { - core: 'fakeCore' + core: 'fakeCore', + log: loggerMock } }; @@ -44,7 +46,7 @@ describe('IntegrationsManagerFactory for browser', () => { expect(instance1).toBe(undefined); // The instance should be undefined if settings.integrations does not contain integrations that register a listener. let integrations: BrowserIntegration[] = [{ type: GOOGLE_ANALYTICS_TO_SPLIT }, { type: SPLIT_TO_GOOGLE_ANALYTICS }]; - const instance2 = browserIMF(integrations, fakeContext as any) as IIntegrationManager; + const instance2 = browserIMF(integrations, fakeParams as any) as IIntegrationManager; expect((GaToSplitMock as jest.Mock).mock.calls.length).toBe(1); // GaToSplit invoked once expect((SplitToGaMock as unknown as jest.Mock).mock.calls.length).toBe(1); // SplitToGa invoked once expect(typeof instance2.handleImpression).toBe('function'); // The instance should implement the handleImpression method if settings.integrations has items that register a listener. @@ -53,7 +55,7 @@ describe('IntegrationsManagerFactory for browser', () => { clearMocks(); integrations = [{ type: GOOGLE_ANALYTICS_TO_SPLIT }, { type: SPLIT_TO_GOOGLE_ANALYTICS }, { type: GOOGLE_ANALYTICS_TO_SPLIT }, { type: SPLIT_TO_GOOGLE_ANALYTICS }, { type: SPLIT_TO_GOOGLE_ANALYTICS }]; - browserIMF(integrations, fakeContext as any); + browserIMF(integrations, fakeParams as any); expect((GaToSplitMock as jest.Mock).mock.calls.length).toBe(2); // GaToSplit invoked twice expect((SplitToGaMock as unknown as jest.Mock).mock.calls.length).toBe(3); // SplitToGa invoked thrice @@ -65,9 +67,9 @@ describe('IntegrationsManagerFactory for browser', () => { type: 'GOOGLE_ANALYTICS_TO_SPLIT', prefix: 'some-prefix' }]; - browserIMF(integrations, fakeContext as any); + browserIMF(integrations, fakeParams as any); - expect((GaToSplitMock as jest.Mock).mock.calls).toEqual([[integrations[0], fakeContext.storage, fakeContext.settings.core]]); // Invokes GaToSplit integration module with options, storage and core settings + expect((GaToSplitMock as jest.Mock).mock.calls).toEqual([[integrations[0], fakeParams]]); // Invokes GaToSplit integration module with options, storage and core settings clearMocks(); }); @@ -77,9 +79,9 @@ describe('IntegrationsManagerFactory for browser', () => { type: 'SPLIT_TO_GOOGLE_ANALYTICS', events: true }]; - const instance = browserIMF(integrations, fakeContext as any); + const instance = browserIMF(integrations, fakeParams as any); - expect((SplitToGaMock as unknown as jest.Mock).mock.calls).toEqual([[integrations[0]]]); // Invokes SplitToGa integration module with options + expect((SplitToGaMock as unknown as jest.Mock).mock.calls).toEqual([[integrations[0], fakeParams.settings.log]]); // Invokes SplitToGa integration module with options const fakeImpression = 'fake'; // @ts-expect-error instance.handleImpression(fakeImpression); diff --git a/src/integrations/ga/GaToSplit.ts b/src/integrations/ga/GaToSplit.ts index b1931121..9803d33e 100644 --- a/src/integrations/ga/GaToSplit.ts +++ b/src/integrations/ga/GaToSplit.ts @@ -1,7 +1,6 @@ /* eslint-disable no-undef */ import objectAssign from 'object-assign'; import { isString, isFiniteNumber, uniqAsStrings } from '../../utils/lang'; -import { logFactory } from '../../logger/sdkLogger'; import { validateEvent, validateEventValue, @@ -9,11 +8,13 @@ import { validateKey, validateTrafficType, } from '../../utils/inputValidation'; -import { IEventsCacheBase } from '../../storages/types'; -import { SplitIO, ISettings } from '../../types'; +import { SplitIO } from '../../types'; import { Identity, GoogleAnalyticsToSplitOptions } from './types'; +import { ILogger } from '../../logger/types'; +import { IIntegrationFactoryParams } from '../types'; +// import { logFactory } from '../../logger/sdkLogger'; const logName = 'splitio-ga-to-split', logNameMapper = logName + ':mapper'; -const log = logFactory(logName); +// const log = logFactory(logName); /** * Provides a plugin to use with analytics.js, accounting for the possibility @@ -125,24 +126,24 @@ export function validateIdentities(identities?: Identity[]) { * @param {EventData} data event data instance to validate. Precondition: data != undefined * @returns {boolean} Whether the data instance is a valid EventData or not. */ -export function validateEventData(eventData: any): eventData is SplitIO.EventData { - if (!validateEvent(eventData.eventTypeId, logNameMapper)) +export function validateEventData(log: ILogger, eventData: any): eventData is SplitIO.EventData { + if (!validateEvent(log, eventData.eventTypeId, logNameMapper)) return false; - if (validateEventValue(eventData.value, logNameMapper) === false) + if (validateEventValue(log, eventData.value, logNameMapper) === false) return false; - const { properties } = validateEventProperties(eventData.properties, logNameMapper); + const { properties } = validateEventProperties(log, eventData.properties, logNameMapper); if (properties === false) return false; if (eventData.timestamp && !isFiniteNumber(eventData.timestamp)) return false; - if (eventData.key && validateKey(eventData.key, logNameMapper) === false) + if (eventData.key && validateKey(log, eventData.key, logNameMapper) === false) return false; - if (eventData.trafficTypeName && validateTrafficType(eventData.trafficTypeName, logNameMapper) === false) + if (eventData.trafficTypeName && validateTrafficType(log, eventData.trafficTypeName, logNameMapper) === false) return false; return true; @@ -156,7 +157,7 @@ const INVALID_SUBSTRING_REGEX = /[^-_.:a-zA-Z0-9]+/g; * @param {string} eventTypeId string value to fix. * @returns {string} Fixed version of `eventTypeId`. */ -export function fixEventTypeId(eventTypeId: any) { +export function fixEventTypeId(eventTypeId: any, log: ILogger) { // return the input eventTypeId if it cannot be fixed if (!isString(eventTypeId) || eventTypeId.length === 0) { return eventTypeId; @@ -178,8 +179,11 @@ export function fixEventTypeId(eventTypeId: any) { * @param {object} sdkOptions options passed at the SDK integrations settings (isomorphic SDK) or the GoogleAnalyticsToSplit plugin (pluggable browser SDK) * @param {object} storage SDK storage passed to track events * @param {object} coreSettings core settings used to define an identity if no one provided as SDK or plugin options + * @param {object} log factory logger */ -export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, storage: { events: IEventsCacheBase }, coreSettings: ISettings['core']) { +export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, params: IIntegrationFactoryParams) { + + const { storage, settings: { core: coreSettings, log } } = params; const defaultOptions = { prefix: defaultPrefix, @@ -254,9 +258,9 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, sto // Add prefix. Nothing is appended if the prefix is falsy, e.g. undefined or ''. if (opts.prefix) eventData.eventTypeId = `${opts.prefix}.${eventData.eventTypeId}`; - eventData.eventTypeId = fixEventTypeId(eventData.eventTypeId); + eventData.eventTypeId = fixEventTypeId(eventData.eventTypeId, log); - if (!validateEventData(eventData)) + if (!validateEventData(log, eventData)) return; // Store the event diff --git a/src/integrations/ga/GaToSplitPlugin.ts b/src/integrations/ga/GaToSplitPlugin.ts index 5a4e9449..04a16905 100644 --- a/src/integrations/ga/GaToSplitPlugin.ts +++ b/src/integrations/ga/GaToSplitPlugin.ts @@ -6,6 +6,6 @@ export default function GaToSplitPlugin(options: GoogleAnalyticsToSplitOptions) // GaToSplit integration factory return (params: IIntegrationFactoryParams) => { - return GaToSplit(options, params.storage, params.settings.core); + return GaToSplit(options, params); }; } diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index d2417da1..881d1952 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -1,11 +1,12 @@ /* eslint-disable no-undef */ -import { logFactory } from '../../logger/sdkLogger'; import { uniq } from '../../utils/lang'; import { SPLIT_IMPRESSION, SPLIT_EVENT } from '../../utils/constants'; import { SplitIO } from '../../types'; import { IIntegration } from '../types'; import { SplitToGoogleAnalyticsOptions } from './types'; -const log = logFactory('splitio-split-to-ga'); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-split-to-ga'); const noGaWarning = '`ga` command queue not found.'; @@ -19,6 +20,7 @@ export default class SplitToGa implements IIntegration { private mapper?: (data: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject) => UniversalAnalytics.FieldsObject; private impressions: boolean | undefined; private events: boolean | undefined; + private log: ILogger; // Default mapper function. static defaultMapper({ type, payload }: SplitIO.IntegrationData): UniversalAnalytics.FieldsObject { @@ -57,7 +59,7 @@ export default class SplitToGa implements IIntegration { * @param {UniversalAnalytics.FieldsObject} fieldsObject object to validate. * @returns {boolean} Whether the data instance is a valid FieldsObject or not. */ - static validateFieldsObject(fieldsObject: any): fieldsObject is UniversalAnalytics.FieldsObject { + static validateFieldsObject(fieldsObject: any, log: ILogger): fieldsObject is UniversalAnalytics.FieldsObject { if (fieldsObject && fieldsObject.hitType) return true; log.w('your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.'); @@ -68,9 +70,10 @@ export default class SplitToGa implements IIntegration { * constructor description * @param {object} options options passed at the SDK integrations settings (isomorphic SDK) or the SplitToGoogleAnalytics plugin (pluggable browser SDK) */ - constructor(options?: SplitToGoogleAnalyticsOptions) { + constructor(options: SplitToGoogleAnalyticsOptions, log: ILogger) { this.trackerNames = SplitToGa.defaultTrackerNames; + this.log = log; if (options) { if (typeof options.filter === 'function') this.filter = options.filter; @@ -108,10 +111,10 @@ export default class SplitToGa implements IIntegration { if (this.mapper) { fieldsObject = this.mapper(data, fieldsObject); // don't send the hit if it is falsy or invalid - if (!fieldsObject || !SplitToGa.validateFieldsObject(fieldsObject)) return; + if (!fieldsObject || !SplitToGa.validateFieldsObject(fieldsObject, this.log)) return; } } catch (err) { - log.w(`SplitToGa queue method threw: ${err}. No hit was sent.`); + this.log.w(`SplitToGa queue method threw: ${err}. No hit was sent.`); return; } @@ -124,7 +127,7 @@ export default class SplitToGa implements IIntegration { ga(sendCommand, fieldsObject); }); } else { - log.w(noGaWarning + ' No hit was sent.'); + this.log.w(noGaWarning + ' No hit was sent.'); } } diff --git a/src/integrations/ga/SplitToGaPlugin.ts b/src/integrations/ga/SplitToGaPlugin.ts index 309ebf53..0556143c 100644 --- a/src/integrations/ga/SplitToGaPlugin.ts +++ b/src/integrations/ga/SplitToGaPlugin.ts @@ -1,10 +1,11 @@ +import { IIntegrationFactoryParams } from '../types'; import SplitToGa from './SplitToGa'; import { SplitToGoogleAnalyticsOptions } from './types'; -export default function SplitToGaPlugin(options: SplitToGoogleAnalyticsOptions) { +export default function SplitToGaPlugin(options: SplitToGoogleAnalyticsOptions = {}) { // SplitToGa integration factory - return () => { - return new SplitToGa(options); + return (params: IIntegrationFactoryParams) => { + return new SplitToGa(options, params.settings.log); }; } diff --git a/src/integrations/ga/__tests__/GaToSplit.spec.ts b/src/integrations/ga/__tests__/GaToSplit.spec.ts index f48dd1c6..96f7c474 100644 --- a/src/integrations/ga/__tests__/GaToSplit.spec.ts +++ b/src/integrations/ga/__tests__/GaToSplit.spec.ts @@ -3,6 +3,7 @@ import { IEventsCacheSync } from '../../../storages/types'; import { SplitIO, ISettings } from '../../../types'; import GaToSplit, { validateIdentities, defaultPrefix, defaultMapper, validateEventData, fixEventTypeId } from '../GaToSplit'; import { gaMock, gaRemove, modelMock } from './gaMock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; const hitSample: UniversalAnalytics.FieldsObject = { hitType: 'pageview', @@ -80,13 +81,13 @@ test('validateEventData', () => { }); test('fixEventTypeId', () => { - expect(fixEventTypeId(undefined)).toBe(undefined); - expect(fixEventTypeId(111)).toBe(111); - expect(fixEventTypeId('')).toBe(''); - expect(fixEventTypeId('()')).toBe(''); - expect(fixEventTypeId('()+_')).toBe(''); - expect(fixEventTypeId(' some event ')).toBe('some_event_'); - expect(fixEventTypeId(' -*- some -.%^ event =+ ')).toBe('some_-._event_'); + expect(fixEventTypeId(undefined, loggerMock)).toBe(undefined); + expect(fixEventTypeId(111, loggerMock)).toBe(111); + expect(fixEventTypeId('', loggerMock)).toBe(''); + expect(fixEventTypeId('()', loggerMock)).toBe(''); + expect(fixEventTypeId('()+_', loggerMock)).toBe(''); + expect(fixEventTypeId(' some event ', loggerMock)).toBe('some_event_'); + expect(fixEventTypeId(' -*- some -.%^ event =+ ', loggerMock)).toBe('some_-._event_'); }); test('defaultMapper', () => { @@ -110,6 +111,11 @@ const fakeStorage = { track: jest.fn() } as IEventsCacheSync }; +const fakeParams = { + storage: fakeStorage, + settings: { core: coreSettings, log: loggerMock } +}; + // Returns a new event by copying defaultEvent function customMapper(model: UniversalAnalytics.Model, defaultEvent: SplitIO.EventData) { return { ...defaultEvent, properties: { ...defaultEvent.properties, someProp: 'someProp' } }; @@ -136,7 +142,7 @@ test('GaToSplit', () => { const { ga, tracker } = gaMock(); // provide SplitTracker plugin - GaToSplit({}, fakeStorage, coreSettings); + GaToSplit({}, fakeParams as any); // @ts-expect-error let [arg1, arg2, SplitTracker] = ga.mock.calls.pop() as [string, string, any]; expect([arg1, arg2]).toEqual(['provide', 'splitTracker']); @@ -180,7 +186,7 @@ test('GaToSplit', () => { // provide a new SplitTracker plugin with custom SDK options GaToSplit({ mapper: customMapper2, filter: customFilter, identities: customIdentities, prefix: '' - }, fakeStorage, coreSettings); + }, fakeParams as any); // @ts-expect-error [arg1, arg2, SplitTracker] = ga.mock.calls.pop(); expect([arg1, arg2]).toEqual(['provide', 'splitTracker']); @@ -205,7 +211,7 @@ test('GaToSplit', () => { // provide a new SplitTracker plugin with custom SDK options GaToSplit({ mapper: customMapper3, filter: customFilter, identities: customIdentities, prefix: '' - }, fakeStorage, coreSettings); + }, fakeParams as any); // @ts-ignore [arg1, arg2, SplitTracker] = ga.mock.calls.pop(); expect([arg1, arg2]).toEqual(['provide', 'splitTracker']); @@ -231,7 +237,7 @@ test('GaToSplit: `hits` flag param', () => { // test setup const { ga, tracker } = gaMock(); - GaToSplit({}, fakeStorage, coreSettings); // @ts-expect-error + GaToSplit({}, fakeParams as any); // @ts-expect-error let SplitTracker: any = ga.mock.calls.pop()[2]; // init plugin with custom options diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index c99729f7..ae007941 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -58,17 +58,17 @@ const defaultEventFieldsObject = { describe('SplitToGa', () => { test('SplitToGa.validateFieldsObject', () => { - expect(SplitToGa.validateFieldsObject(undefined)).toBe(false); - expect(SplitToGa.validateFieldsObject(null)).toBe(false); - expect(SplitToGa.validateFieldsObject(123)).toBe(false); - expect(SplitToGa.validateFieldsObject(true)).toBe(false); - expect(SplitToGa.validateFieldsObject('something')).toBe(false); - expect(SplitToGa.validateFieldsObject(/asd/ig)).toBe(false); - expect(SplitToGa.validateFieldsObject(function () { })).toBe(false); - - expect(SplitToGa.validateFieldsObject({})).toBe(false); // An empty object is an invalid FieldsObject instance - expect(SplitToGa.validateFieldsObject({ hitType: 10 })).toBe(true); // A fields object instance must have a HitType - expect(SplitToGa.validateFieldsObject({ hitType: 'event', ignoredProp: 'ignoredProp' })).toBe(true); // A fields object instance must have a HitType + expect(SplitToGa.validateFieldsObject(undefined, loggerMock)).toBe(false); + expect(SplitToGa.validateFieldsObject(null, loggerMock)).toBe(false); + expect(SplitToGa.validateFieldsObject(123, loggerMock)).toBe(false); + expect(SplitToGa.validateFieldsObject(true, loggerMock)).toBe(false); + expect(SplitToGa.validateFieldsObject('something', loggerMock)).toBe(false); + expect(SplitToGa.validateFieldsObject(/asd/ig, loggerMock)).toBe(false); + expect(SplitToGa.validateFieldsObject(function () { }, loggerMock)).toBe(false); + + expect(SplitToGa.validateFieldsObject({}, loggerMock)).toBe(false); // An empty object is an invalid FieldsObject instance + expect(SplitToGa.validateFieldsObject({ hitType: 10 }, loggerMock)).toBe(true); // A fields object instance must have a HitType + expect(SplitToGa.validateFieldsObject({ hitType: 'event', ignoredProp: 'ignoredProp' }, loggerMock)).toBe(true); // A fields object instance must have a HitType }); test('SplitToGa.defaultMapper', () => { @@ -84,14 +84,14 @@ describe('SplitToGa', () => { const { ga } = gaMock(); expect(SplitToGa.getGa()).toBe(ga); // should return ga command queue if it exists - let integration = new SplitToGa(); + let integration = new SplitToGa({}, loggerMock); expect(typeof integration).toBe('object'); expect(loggerMock.w.mock.calls.length).toBe(0); gaRemove(); expect(SplitToGa.getGa()).toBe(undefined); // should return undefined if ga command queue does not exist - integration = new SplitToGa(); + integration = new SplitToGa({}, loggerMock); expect(typeof integration).toBe('object'); // SplitToGa instances should be created even if ga command queue does not exist // @ts-expect-error integration.queue('fake-data'); @@ -107,7 +107,7 @@ describe('SplitToGa', () => { const { ga } = gaMock(); /** Default behaviour **/ - const instance = new SplitToGa() as SplitToGa; + const instance = new SplitToGa({}, loggerMock) as SplitToGa; instance.queue(fakeImpression); // should queue `ga send` with the default mapped FieldsObject for impressions, appended with `splitHit` field expect(ga.mock.calls[ga.mock.calls.length - 1]).toEqual(['send', { ...defaultImpressionFieldsObject, splitHit: true }]); @@ -135,7 +135,7 @@ describe('SplitToGa', () => { filter: customFilter, mapper: customMapper, trackerNames, - }) as SplitToGa; + }, loggerMock) as SplitToGa; ga.mockClear(); instance2.queue(fakeImpression); expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` if a Split data (impression or event) is filtered @@ -154,7 +154,7 @@ describe('SplitToGa', () => { } const instance3 = new SplitToGa({ mapper: customMapper2, - }) as SplitToGa; + }, loggerMock) as SplitToGa; ga.mockClear(); instance3.queue(fakeImpression); // should queue `ga send` with the custom FieldsObject from customMapper2, appended with `splitHit` field @@ -168,7 +168,7 @@ describe('SplitToGa', () => { } const instance4 = new SplitToGa({ // @ts-expect-error mapper: customMapper3, - }) as SplitToGa; + }, loggerMock) as SplitToGa; ga.mockClear(); instance4.queue(fakeImpression); expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` if a custom mapper throw an exception @@ -176,7 +176,7 @@ describe('SplitToGa', () => { // `impressions` flags const instance5 = new SplitToGa({ impressions: false, - }) as SplitToGa; + }, loggerMock) as SplitToGa; ga.mockClear(); instance5.queue(fakeImpression); expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` for an impression if `impressions` flag is false @@ -184,7 +184,7 @@ describe('SplitToGa', () => { // `impressions` flags const instance6 = new SplitToGa({ events: false, - }) as SplitToGa; + }, loggerMock) as SplitToGa; ga.mockClear(); instance6.queue(fakeEvent); expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` for a event if `events` flag is false diff --git a/src/listeners/__tests__/node.spec.ts b/src/listeners/__tests__/node.spec.ts index ad8c0598..57deeea4 100644 --- a/src/listeners/__tests__/node.spec.ts +++ b/src/listeners/__tests__/node.spec.ts @@ -1,4 +1,6 @@ import NodeSignalListener from '../node'; +import { settingsSplitApi } from '../../utils/settingsValidation/__tests__/settings.mocks'; +const fakeSettings = settingsSplitApi; const processOnSpy = jest.spyOn(process, 'on'); const processRemoveListenerSpy = jest.spyOn(process, 'removeListener'); @@ -7,7 +9,7 @@ const processKillSpy = jest.spyOn(process, 'kill').mockImplementation(() => true test('Node JS listener / Signal Listener class methods and start/stop functionality', () => { const handlerMock = jest.fn(); - const listener = new NodeSignalListener(handlerMock); + const listener = new NodeSignalListener(handlerMock, fakeSettings); listener.start(); @@ -27,7 +29,7 @@ test('Node JS listener / Signal Listener class methods and start/stop functional test('Node JS listener / Signal Listener SIGTERM callback with sync handler', () => { const handlerMock = jest.fn(); - const listener = new NodeSignalListener(handlerMock); + const listener = new NodeSignalListener(handlerMock, fakeSettings); listener.start(); // Stub stop function since we don't want side effects on test. @@ -56,7 +58,7 @@ test('Node JS listener / Signal Listener SIGTERM callback with sync handler', () test('Node JS listener / Signal Listener SIGTERM callback with sync handler that throws an error', () => { const handlerMock = jest.fn(() => { throw 'some error'; }); - const listener = new NodeSignalListener(handlerMock); + const listener = new NodeSignalListener(handlerMock, fakeSettings); listener.start(); // Stub stop function since we don't want side effects on test. @@ -93,7 +95,7 @@ test('Node JS listener / Signal Listener SIGTERM callback with async handler', a }); const handlerMock = jest.fn(() => fakePromise); - const listener = new NodeSignalListener(handlerMock); + const listener = new NodeSignalListener(handlerMock, fakeSettings); // Stub stop function since we don't want side effects on test. jest.spyOn(listener, 'stop'); @@ -137,7 +139,7 @@ test('Node JS listener / Signal Listener SIGTERM callback with async handler tha }); const handlerMock = jest.fn(() => fakePromise); - const listener = new NodeSignalListener(handlerMock); + const listener = new NodeSignalListener(handlerMock, fakeSettings); // Stub stop function since we don't want side effects on test. jest.spyOn(listener, 'stop'); diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index caa27a18..c6052f0b 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -1,7 +1,6 @@ /* eslint-disable no-undef */ // @TODO eventually migrate to JS-Browser-SDK package. import { ISignalListener } from './types'; -import { logFactory } from '../logger/sdkLogger'; import { IRecorderCacheConsumerSync, IStorageSync } from '../storages/types'; import { fromImpressionsCollector } from '../sync/submitters/impressionsSyncTask'; import { fromImpressionCountsCollector } from '../sync/submitters/impressionCountsSyncTask'; @@ -12,7 +11,8 @@ import { MaybeThenable } from '../dtos/types'; import { OPTIMIZED, DEBUG } from '../utils/constants'; import objectAssign from 'object-assign'; -const log = logFactory('splitio-client:cleanup'); +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio-client:cleanup'); // 'unload' event is used instead of 'beforeunload', since 'unload' is not a cancelable event, so no other listeners can stop the event from occurring. const UNLOAD_DOM_EVENT = 'unload'; @@ -41,7 +41,7 @@ export default class BrowserSignalListener implements ISignalListener { */ start() { if (typeof window !== 'undefined' && window.addEventListener) { - log.d('Registering flush handler when unload page event is triggered.'); + this.settings.log.d('Registering flush handler when unload page event is triggered.'); window.addEventListener(UNLOAD_DOM_EVENT, this.flushData); } } @@ -53,7 +53,7 @@ export default class BrowserSignalListener implements ISignalListener { */ stop() { if (typeof window !== 'undefined' && window.removeEventListener) { - log.d('Deregistering flush handler when unload page event is triggered.'); + this.settings.log.d('Deregistering flush handler when unload page event is triggered.'); window.removeEventListener(UNLOAD_DOM_EVENT, this.flushData); } } diff --git a/src/listeners/node.ts b/src/listeners/node.ts index 42e8a965..7c1ff408 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -1,9 +1,10 @@ // @TODO eventually migrate to JS-Node-SDK package. import { ISignalListener } from './types'; import thenable from '../utils/promise/thenable'; -import { logFactory } from '../logger/sdkLogger'; import { MaybeThenable } from '../dtos/types'; -const log = logFactory('splitio-client:cleanup'); +import { ISettings } from '../types'; +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio-client:cleanup'); /** * We'll listen for SIGTERM since it's the standard signal for server shutdown. @@ -13,21 +14,22 @@ const log = logFactory('splitio-client:cleanup'); * the process is already exiting. */ export default class NodeSignalListener implements ISignalListener { - private handler: any; - constructor(handler: () => MaybeThenable) { - this.handler = handler; + constructor( + private handler: () => MaybeThenable, + private settings: ISettings + ) { this._sigtermHandler = this._sigtermHandler.bind(this); } start() { - log.d('Registering cleanup handlers.'); + this.settings.log.d('Registering cleanup handlers.'); // eslint-disable-next-line no-undef process.on('SIGTERM', this._sigtermHandler); } stop() { - log.d('Deregistering cleanup handlers.'); + this.settings.log.d('Deregistering cleanup handlers.'); // eslint-disable-next-line no-undef process.removeListener('SIGTERM', this._sigtermHandler); } @@ -45,14 +47,14 @@ export default class NodeSignalListener implements ISignalListener { process.kill(process.pid, 'SIGTERM'); }; - log.d('Split SDK graceful shutdown after SIGTERM.'); + this.settings.log.d('Split SDK graceful shutdown after SIGTERM.'); let handlerResult = null; try { handlerResult = this.handler(); } catch (err) { - log.e(`Error with Split graceful shutdown: ${err}`); + this.settings.log.e(`Error with Split graceful shutdown: ${err}`); } if (thenable(handlerResult)) { diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index 705eebf8..01267f5c 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -9,17 +9,13 @@ import { } from './readinessManager'; import { ISdkReadinessManager } from './types'; import { IEventEmitter } from '../types'; -import { logFactory } from '../logger/sdkLogger'; -const log = logFactory(''); +import { ILogger } from '../logger/types'; +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory(''); const NEW_LISTENER_EVENT = 'newListener'; const REMOVE_LISTENER_EVENT = 'removeListener'; -// default onRejected handler, that just logs the error, if ready promise doesn't have one. -function defaultOnRejected(err: any) { - log.e(err); -} - /** * SdkReadinessManager factory, which provides the public status API of SDK clients and manager: ready promise, readiness event emitter and constants (SDK_READY, etc). * It also updates logs related warnings and errors. @@ -31,6 +27,7 @@ function defaultOnRejected(err: any) { */ export default function sdkReadinessManagerFactory( EventEmitter: new () => IEventEmitter, + log: ILogger, readyTimeout = 0, internalReadyCbCount = 0, readinessManager = readinessManagerFactory(EventEmitter, readyTimeout)): ISdkReadinessManager { @@ -58,6 +55,11 @@ export default function sdkReadinessManagerFactory( log.i('Split SDK is ready from cache.'); }); + // default onRejected handler, that just logs the error, if ready promise doesn't have one. + function defaultOnRejected(err: any) { + log.e(err); + } + function generateReadyPromise() { const promise = promiseWrapper(new Promise((resolve, reject) => { readinessManager.gate.once(SDK_READY, () => { @@ -75,7 +77,7 @@ export default function sdkReadinessManagerFactory( readinessManager, shared(readyTimeout = 0, internalReadyCbCount = 0) { - return sdkReadinessManagerFactory(EventEmitter, readyTimeout, internalReadyCbCount, readinessManager.shared(readyTimeout)); + return sdkReadinessManagerFactory(EventEmitter, log, readyTimeout, internalReadyCbCount, readinessManager.shared(readyTimeout)); }, sdkStatus: objectAssign( diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index b8b095ce..041949db 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -8,8 +8,8 @@ import { CONTROL } from '../utils/constants'; import { IClientFactoryParams } from './types'; import { IEvaluationResult } from '../evaluator/types'; import { SplitIO, ImpressionDTO } from '../types'; -import { logFactory } from '../logger/sdkLogger'; -const log = logFactory('splitio-client'); +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio-client'); /** @@ -17,7 +17,7 @@ const log = logFactory('splitio-client'); */ // @TODO missing time tracking to collect telemetry export default function clientFactory(params: IClientFactoryParams): SplitIO.IClient | SplitIO.IAsyncClient { - const { sdkReadinessManager: { readinessManager }, storage, settings, impressionsTracker, eventTracker } = params; + const { sdkReadinessManager: { readinessManager }, storage, settings: { log, mode }, impressionsTracker, eventTracker } = params; function getTreatment(key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, withConfig = false) { const wrapUp = (evaluationResult: IEvaluationResult) => { @@ -78,7 +78,7 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl const { treatment, label, changeNumber, config = null } = evaluation; log.i(`Split: ${splitName}. Key: ${matchingKey}. Evaluation: ${treatment}. Label: ${label}`); - if (validateSplitExistance(readinessManager, splitName, label, invokingMethodName)) { + if (validateSplitExistance(log, readinessManager, splitName, label, invokingMethodName)) { log.i('Queueing corresponding impression.'); queue.push({ feature: splitName, @@ -114,7 +114,7 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl }; // This may be async but we only warn, we don't actually care if it is valid or not in terms of queueing the event. - validateTrafficTypeExistance(readinessManager, storage.splits, settings.mode, trafficTypeName, 'track'); + validateTrafficTypeExistance(log, readinessManager, storage.splits, mode, trafficTypeName, 'track'); return eventTracker.track(eventData as SplitIO.EventData, size); } diff --git a/src/sdkClient/clientInputValidation.ts b/src/sdkClient/clientInputValidation.ts index 262037df..e52b311d 100644 --- a/src/sdkClient/clientInputValidation.ts +++ b/src/sdkClient/clientInputValidation.ts @@ -16,24 +16,25 @@ import { CONTROL, CONTROL_WITH_CONFIG } from '../utils/constants'; import { IReadinessManager } from '../readiness/types'; import { MaybeThenable } from '../dtos/types'; import { SplitIO } from '../types'; +import { ILogger } from '../logger/types'; /** * Decorator that validates the input before actually executing the client methods. * We should "guard" the client here, while not polluting the "real" implementation of those methods. */ -export default function clientInputValidationDecorator(client: TClient, readinessManager: IReadinessManager, isStorageSync = false): TClient { +export default function clientInputValidationDecorator(client: TClient, readinessManager: IReadinessManager, isStorageSync = false, log: ILogger): TClient { /** * Avoid repeating this validations code */ function validateEvaluationParams(maybeKey: SplitIO.SplitKey, maybeSplitOrSplits: string | string[], maybeAttributes: SplitIO.Attributes | undefined, methodName: string) { const multi = startsWith(methodName, 'getTreatments'); - const key = validateKey(maybeKey, methodName); - const splitOrSplits = multi ? validateSplits(maybeSplitOrSplits, methodName) : validateSplit(maybeSplitOrSplits, methodName); - const attributes = validateAttributes(maybeAttributes, methodName); - const isOperational = validateIfNotDestroyed(readinessManager); + const key = validateKey(log, maybeKey, methodName); + const splitOrSplits = multi ? validateSplits(log, maybeSplitOrSplits, methodName) : validateSplit(log, maybeSplitOrSplits, methodName); + const attributes = validateAttributes(log, maybeAttributes, methodName); + const isOperational = validateIfNotDestroyed(log, readinessManager); - validateIfOperational(readinessManager, methodName); + validateIfOperational(log, readinessManager, methodName); const valid = isOperational && key && splitOrSplits && attributes !== false; @@ -97,12 +98,12 @@ export default function clientInputValidationDecorator SplitIO.IClient | SplitIO.IAsyncClient { - + const log = params.settings.log; const clientInstance = sdkClientFactory(params); return function client() { diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index 3012b854..35826036 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -2,13 +2,13 @@ import clientCSDecorator from './clientCS'; import { ISdkClientFactoryParams } from './types'; import { SplitIO } from '../types'; import { validateKey } from '../utils/inputValidation/key'; -import { logFactory } from '../logger/sdkLogger'; import { getMatching, keyParser } from '../utils/key'; import { sdkClientFactory } from './sdkClient'; import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; -const log = logFactory('splitio'); +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio'); function buildInstanceId(key: SplitIO.SplitKey) { // @ts-ignore @@ -20,12 +20,12 @@ function buildInstanceId(key: SplitIO.SplitKey) { * clients don't have a binded TT for the track method. */ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?: SplitIO.SplitKey) => SplitIO.ICsClient { - const { storage, syncManager, sdkReadinessManager, settings: { core: { key }, startup: { readyTimeout } } } = params; + const { storage, syncManager, sdkReadinessManager, settings: { core: { key }, startup: { readyTimeout }, log } } = params; // Keeping similar behaviour as in the isomorphic JS SDK: if settings key is invalid, // `false` value is used as binded key of the default client, but trafficType is ignored // @TODO handle as a non-recoverable error - const validKey = validateKey(key, 'Client instantiation'); + const validKey = validateKey(log, key, 'Client instantiation'); const mainClientInstance = clientCSDecorator( sdkClientFactory(params) as SplitIO.IClient, // @ts-ignore @@ -46,7 +46,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? } // Validate the key value. The trafficType (2nd argument) is ignored - const validKey = validateKey(key, 'Shared Client instantiation'); + const validKey = validateKey(log, key, 'Shared Client instantiation'); if (validKey === false) { throw new Error('Shared Client needs a valid key.'); } diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index a85e7852..dd3230ff 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -3,13 +3,13 @@ import { ISdkClientFactoryParams } from './types'; import { SplitIO } from '../types'; import { validateKey } from '../utils/inputValidation/key'; import { validateTrafficType } from '../utils/inputValidation/trafficType'; -import { logFactory } from '../logger/sdkLogger'; import { getMatching, keyParser } from '../utils/key'; import { sdkClientFactory } from './sdkClient'; import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; -const log = logFactory('splitio'); +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio'); function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string) { // @ts-ignore @@ -22,15 +22,15 @@ function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string) { * (default client) or the client method (shared clients). */ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?: SplitIO.SplitKey, trafficType?: string) => SplitIO.ICsClient { - const { storage, syncManager, sdkReadinessManager, settings: { core: { key, trafficType }, startup: { readyTimeout } } } = params; + const { storage, syncManager, sdkReadinessManager, settings: { core: { key, trafficType }, startup: { readyTimeout }, log } } = params; // Keeping the behaviour as in the isomorphic JS SDK: if settings key or TT are invalid, // `false` value is used as binded key/TT of the default client, which leads to several issues. // @TODO update when supporting non-recoverable errors - const validKey = validateKey(key, 'Client instantiation'); + const validKey = validateKey(log, key, 'Client instantiation'); let validTrafficType; if (trafficType !== undefined) { - validTrafficType = validateTrafficType(trafficType, 'Client instantiation'); + validTrafficType = validateTrafficType(log, trafficType, 'Client instantiation'); } const mainClientInstance = clientCSDecorator( @@ -53,14 +53,14 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? } // Validate the key value - const validKey = validateKey(key, 'Shared Client instantiation'); + const validKey = validateKey(log, key, 'Shared Client instantiation'); if (validKey === false) { throw new Error('Shared Client needs a valid key.'); } let validTrafficType; if (trafficType !== undefined) { - validTrafficType = validateTrafficType(trafficType, 'Shared Client instantiation'); + validTrafficType = validateTrafficType(log, trafficType, 'Shared Client instantiation'); if (validTrafficType === false) { throw new Error('Shared Client needs a valid traffic type or no traffic type at all.'); } diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 568c2038..b2bb0ed8 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -1,6 +1,5 @@ import { ISdkFactoryParams } from './types'; import sdkReadinessManagerFactory from '../readiness/sdkReadinessManager'; -import { logFactory, API } from '../logger/sdkLogger'; import buildMetadata from '../utils/settingsValidation/buildMetadata'; import impressionsTrackerFactory from '../trackers/impressionsTracker'; import eventTrackerFactory from '../trackers/eventTracker'; @@ -10,8 +9,9 @@ import { ISplitApi } from '../services/types'; import { getMatching } from '../utils/key'; import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; - -const log = logFactory('splitio'); +import { API } from '../logger/sdkLogger'; +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio'); /** * Modular SDK factory @@ -21,15 +21,16 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. const { settings, platform, storageFactory, splitApiFactory, syncManagerFactory, SignalListener, impressionsObserverFactory, impressionListener, integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory } = params; + const log = settings.log; // @TODO handle non-recoverable errors: not start sync, mark the SDK as destroyed, etc. // We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle. - validateAndTrackApiKey(settings.core.authorizationKey); + validateAndTrackApiKey(log, settings.core.authorizationKey); const metadata = buildMetadata(settings); // @TODO handle non-recoverable error, such as, `fetch` api not available, invalid API Key, etc. - const sdkReadinessManager = sdkReadinessManagerFactory(platform.EventEmitter, settings.startup.readyTimeout); + const sdkReadinessManager = sdkReadinessManagerFactory(platform.EventEmitter, log, settings.startup.readyTimeout); const storageFactoryParams = { eventsQueueSize: settings.scheduler.eventsQueueSize, @@ -44,7 +45,8 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // ATM, only used by InRedisStorage. @TODO pass a callback to simplify custom storages. readinessManager: sdkReadinessManager.readinessManager, - metadata + metadata, + log }; const storage = storageFactory(storageFactoryParams); @@ -64,15 +66,15 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // trackers const observer = impressionsObserverFactory && impressionsObserverFactory(); - const impressionsTracker = impressionsTrackerFactory(storage.impressions, metadata, impressionListener, integrationsManager, observer, storage.impressionCounts); - const eventTracker = eventTrackerFactory(storage.events, integrationsManager); + const impressionsTracker = impressionsTrackerFactory(log, storage.impressions, metadata, impressionListener, integrationsManager, observer, storage.impressionCounts); + const eventTracker = eventTrackerFactory(log, storage.events, integrationsManager); // signal listener const signalListener = SignalListener && new SignalListener(syncManager && syncManager.flush, settings, storage, splitApi); // Sdk client and manager const clientMethod = sdkClientMethodFactory({ eventTracker, impressionsTracker, sdkReadinessManager, settings, storage, syncManager, signalListener }); - const managerInstance = sdkManagerFactory && sdkManagerFactory(storage.splits, sdkReadinessManager); + const managerInstance = sdkManagerFactory && sdkManagerFactory(storage.splits, sdkReadinessManager, log); syncManager && syncManager.start(); signalListener && signalListener.start(); diff --git a/src/sdkFactory/types.ts b/src/sdkFactory/types.ts index 22b34646..2799234b 100644 --- a/src/sdkFactory/types.ts +++ b/src/sdkFactory/types.ts @@ -1,6 +1,7 @@ import { MaybeThenable } from '../dtos/types'; import { IIntegrationManager, IIntegrationFactoryParams } from '../integrations/types'; import { ISignalListener } from '../listeners/types'; +import { ILogger } from '../logger/types'; import { ISdkReadinessManager } from '../readiness/types'; import { ISdkClientFactoryParams } from '../sdkClient/types'; import { IFetch, ISplitApi } from '../services/types'; @@ -47,7 +48,8 @@ export interface ISdkFactoryParams { // Sdk manager factory sdkManagerFactory?: ( splits: ISplitsCacheSync | ISplitsCacheAsync, - sdkReadinessManager: ISdkReadinessManager + sdkReadinessManager: ISdkReadinessManager, + log: ILogger ) => SplitIO.IManager | SplitIO.IAsyncManager, // Sdk client method factory (ISDK::client method). diff --git a/src/sdkManager/index.ts b/src/sdkManager/index.ts index f5a9051b..779479c8 100644 --- a/src/sdkManager/index.ts +++ b/src/sdkManager/index.ts @@ -6,6 +6,7 @@ import { ISplitsCacheAsync, ISplitsCacheSync } from '../storages/types'; import { ISdkReadinessManager } from '../readiness/types'; import { ISplit } from '../dtos/types'; import { SplitIO } from '../types'; +import { ILogger } from '../logger/types'; function collectTreatments(splitObject: ISplit) { const conditions = splitObject.conditions; @@ -52,7 +53,8 @@ function objectsToViews(jsons: string[]) { export function sdkManagerFactory( splits: TSplitCache, - { readinessManager, sdkStatus }: ISdkReadinessManager + { readinessManager, sdkStatus }: ISdkReadinessManager, + log: ILogger ): TSplitCache extends ISplitsCacheAsync ? SplitIO.IAsyncManager : SplitIO.IManager { const SPLIT_FN_LABEL = 'split'; @@ -64,8 +66,8 @@ export function sdkManagerFactory { - validateSplitExistance(readinessManager, splitName, result, SPLIT_FN_LABEL); + validateSplitExistance(log, readinessManager, splitName, result, SPLIT_FN_LABEL); return objectToView(result); }); } - validateSplitExistance(readinessManager, splitName, split, SPLIT_FN_LABEL); + validateSplitExistance(log, readinessManager, splitName, split, SPLIT_FN_LABEL); return objectToView(split); }, @@ -86,7 +88,7 @@ export function sdkManagerFactory (IFetch | undefined), getOptions?: () => object): ISplitHttpClient { +export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: IMetadata, getFetch?: () => (IFetch | undefined), getOptions?: () => object): ISplitHttpClient { const options = getOptions && getOptions(); const fetch = getFetch && getFetch(); @@ -33,7 +34,7 @@ export function splitHttpClientFactory(apikey: string, metadata: IMetadata, getF if (metadata.ip) headers['SplitSDKMachineIP'] = metadata.ip; if (metadata.hostname) headers['SplitSDKMachineName'] = metadata.hostname; - return function httpClient(url: string, method: string = 'GET', body?: string, logErrorsAsInfo: boolean = false, extraHeaders?: Record): Promise { + return function httpClient(url: string, method: string = 'GET', body?: string, extraHeaders?: Record): Promise { const rHeaders = extraHeaders ? objectAssign({}, headers, extraHeaders) : headers; const request = objectAssign({ headers: rHeaders, method, body }, options); @@ -62,7 +63,7 @@ export function splitHttpClientFactory(apikey: string, metadata: IMetadata, getF } if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else. - log[logErrorsAsInfo ? 'i' : 'e'](`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); + log.e(`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); } // passes `undefined` as statusCode if not an HTTP error (resp === undefined) diff --git a/src/services/types.ts b/src/services/types.ts index ba134f5d..f2603513 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -8,7 +8,7 @@ export type IFetch = ( } ) => Promise -export type ISplitHttpClient = (url: string, method?: string, body?: string, logErrorsAsInfo?: boolean, extraHeaders?: Record) => Promise +export type ISplitHttpClient = (url: string, method?: string, body?: string, extraHeaders?: Record) => Promise export type IFetchAuth = (userKeys?: string[]) => Promise diff --git a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts index c13f4e44..b4e1c0ac 100644 --- a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +++ b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts @@ -1,16 +1,19 @@ +import { ILogger } from '../../logger/types'; import AbstractSegmentsCacheSync from '../AbstractSegmentsCacheSync'; -import { logFactory } from '../../logger/sdkLogger'; import KeyBuilderCS from '../KeyBuilderCS'; -const log = logFactory('splitio-storage:localstorage'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-storage:localstorage'); const DEFINED = '1'; export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { private readonly keys: KeyBuilderCS; + private readonly log: ILogger; - constructor(keys: KeyBuilderCS) { + constructor(log: ILogger, keys: KeyBuilderCS) { super(); + this.log = log; this.keys = keys; // There is not need to flush segments cache like splits cache, since resetSegments receives the up-to-date list of active segments } @@ -20,7 +23,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { * @NOTE this method is not being used at the moment. */ clear() { - log.i('Flushing MySegments data from localStorage'); + this.log.i('Flushing MySegments data from localStorage'); // We cannot simply call `localStorage.clear()` since that implies removing user items from the storage // We could optimize next sentence, since it implies iterating over all localStorage items @@ -34,7 +37,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { localStorage.setItem(segmentKey, DEFINED); return true; } catch (e) { - log.e(e); + this.log.e(e); return false; } } @@ -46,7 +49,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { localStorage.removeItem(segmentKey); return true; } catch (e) { - log.e(e); + this.log.e(e); return false; } } diff --git a/src/storages/inLocalStorage/SplitsCacheInLocal.ts b/src/storages/inLocalStorage/SplitsCacheInLocal.ts index 7067b67f..f12156c7 100644 --- a/src/storages/inLocalStorage/SplitsCacheInLocal.ts +++ b/src/storages/inLocalStorage/SplitsCacheInLocal.ts @@ -2,8 +2,9 @@ import { ISplit, ISplitFiltersValidation } from '../../dtos/types'; import AbstractSplitsCacheSync, { usesSegments } from '../AbstractSplitsCacheSync'; import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang'; import KeyBuilderCS from '../KeyBuilderCS'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-storage:localstorage'); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-storage:localstorage'); /** * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage. @@ -21,7 +22,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { * @param {number | undefined} expirationTimestamp * @param {ISplitFiltersValidation} splitFiltersValidation */ - constructor(keys: KeyBuilderCS, expirationTimestamp?: number, splitFiltersValidation: ISplitFiltersValidation = { queryString: null, groupedFilters: { byName: [], byPrefix: [] }, validFilters: [] }) { + constructor(private readonly log: ILogger, keys: KeyBuilderCS, expirationTimestamp?: number, splitFiltersValidation: ISplitFiltersValidation = { queryString: null, groupedFilters: { byName: [], byPrefix: [] }, validFilters: [] }) { super(); this.keys = keys; this.splitFiltersValidation = splitFiltersValidation; @@ -52,7 +53,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { } } } catch (e) { - log.e(e); + this.log.e(e); } } @@ -72,7 +73,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { } } } catch (e) { - log.e(e); + this.log.e(e); } } @@ -82,7 +83,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { * We cannot simply call `localStorage.clear()` since that implies removing user items from the storage. */ clear() { - log.i('Flushing Splits data from localStorage'); + this.log.i('Flushing Splits data from localStorage'); // collect item keys const len = localStorage.length; @@ -114,7 +115,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { return true; } catch (e) { - log.e(e); + this.log.e(e); return false; } } @@ -129,7 +130,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { return 1; } catch (e) { - log.e(e); + this.log.e(e); return 0; } } @@ -147,14 +148,14 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { // when using a new split query, we must update it at the store if (this.updateNewFilter) { - log.i('Split filter query was modified. Updating cache.'); + this.log.i('Split filter query was modified. Updating cache.'); const queryKey = this.keys.buildSplitsFilterQueryKey(); const queryString = this.splitFiltersValidation.queryString; try { if (queryString) localStorage.setItem(queryKey, queryString); else localStorage.removeItem(queryKey); } catch (e) { - log.e(e); + this.log.e(e); } this.updateNewFilter = false; } @@ -166,7 +167,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { this.hasSync = true; return true; } catch (e) { - log.e(e); + this.log.e(e); return false; } } @@ -273,7 +274,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { }); } } catch (e) { - log.e(e); + this.log.e(e); } } // if the filter didn't change, nothing is done diff --git a/src/storages/inLocalStorage/index.ts b/src/storages/inLocalStorage/index.ts index 415e4196..fa2f3fbb 100644 --- a/src/storages/inLocalStorage/index.ts +++ b/src/storages/inLocalStorage/index.ts @@ -6,10 +6,10 @@ import KeyBuilderCS from '../KeyBuilderCS'; import { isLocalStorageAvailable } from '../../utils/env/isLocalStorageAvailable'; import SplitsCacheInLocal from './SplitsCacheInLocal'; import MySegmentsCacheInLocal from './MySegmentsCacheInLocal'; -import { logFactory } from '../../logger/sdkLogger'; import MySegmentsCacheInMemory from '../inMemory/MySegmentsCacheInMemory'; import SplitsCacheInMemory from '../inMemory/SplitsCacheInMemory'; import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser'; +import { logFactory } from '../../logger/sdkLogger'; const log = logFactory('splitio-storage:localstorage'); export interface InLocalStorageOptions { @@ -31,12 +31,13 @@ export function InLocalStorage(options: InLocalStorageOptions = {}) { return function InLocalStorageCSFactory(params: IStorageFactoryParams): IStorageSyncCS { + const log = params.log; const keys = new KeyBuilderCS(prefix, params.matchingKey as string); const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS; return { - splits: new SplitsCacheInLocal(keys, expirationTimestamp, params.splitFiltersValidation), - segments: new MySegmentsCacheInLocal(keys), + splits: new SplitsCacheInLocal(log, keys, expirationTimestamp, params.splitFiltersValidation), + segments: new MySegmentsCacheInLocal(log, keys), impressions: new ImpressionsCacheInMemory(), impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined, events: new EventsCacheInMemory(params.eventsQueueSize), @@ -55,7 +56,7 @@ export function InLocalStorage(options: InLocalStorageOptions = {}) { return { splits: this.splits, - segments: new MySegmentsCacheInLocal(childKeysBuilder), + segments: new MySegmentsCacheInLocal(log, childKeysBuilder), impressions: this.impressions, impressionCounts: this.impressionCounts, events: this.events, diff --git a/src/storages/inRedis/EventsCacheInRedis.ts b/src/storages/inRedis/EventsCacheInRedis.ts index fc6ffa5c..13e4cc35 100644 --- a/src/storages/inRedis/EventsCacheInRedis.ts +++ b/src/storages/inRedis/EventsCacheInRedis.ts @@ -1,10 +1,11 @@ import { IEventsCacheAsync } from '../types'; import { IRedisMetadata } from '../../dtos/types'; import KeyBuilderSS from '../KeyBuilderSS'; -import { logFactory } from '../../logger/sdkLogger'; import { Redis } from 'ioredis'; import { SplitIO } from '../../types'; -const log = logFactory('splitio-storage:redis'); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-storage:redis'); export default class EventsCacheInRedis implements IEventsCacheAsync { @@ -13,7 +14,7 @@ export default class EventsCacheInRedis implements IEventsCacheAsync { private readonly metadata: IRedisMetadata; private readonly eventsKey: string; - constructor(keys: KeyBuilderSS, redis: Redis, metadata: IRedisMetadata) { + constructor(private readonly log: ILogger, keys: KeyBuilderSS, redis: Redis, metadata: IRedisMetadata) { this.keys = keys; this.redis = redis; this.metadata = metadata; @@ -32,7 +33,7 @@ export default class EventsCacheInRedis implements IEventsCacheAsync { // We use boolean values to signal successful queueing .then(() => true) .catch(err => { - log.e(`Error adding event to queue: ${err}.`); + this.log.e(`Error adding event to queue: ${err}.`); return false; }); } diff --git a/src/storages/inRedis/RedisAdapter.ts b/src/storages/inRedis/RedisAdapter.ts index 0ff1b73e..198d890f 100644 --- a/src/storages/inRedis/RedisAdapter.ts +++ b/src/storages/inRedis/RedisAdapter.ts @@ -1,10 +1,11 @@ import ioredis from 'ioredis'; +import { ILogger } from '../../logger/types'; import { merge, isString } from '../../utils/lang'; import { _Set, setToArray, ISet } from '../../utils/lang/sets'; import thenable from '../../utils/promise/thenable'; import timeout from '../../utils/promise/timeout'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-storage:redis-adapter'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-storage:redis-adapter'); // If we ever decide to fully wrap every method, there's a Commander.getBuiltinCommands from ioredis. const METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', 'pipeline', 'expire', 'mget']; @@ -32,15 +33,17 @@ interface IRedisCommand { * Redis adapter on top of the library of choice (written with ioredis) for some extra control. */ export default class RedisAdapter extends ioredis { + private readonly log: ILogger private _options: object; private _notReadyCommandsQueue?: IRedisCommand[]; private _runningCommands: ISet>; - constructor(storageSettings: Record) { + constructor(log: ILogger, storageSettings: Record) { const options = RedisAdapter._defineOptions(storageSettings); // Call the ioredis constructor super(...RedisAdapter._defineLibrarySettings(options)); + this.log = log; this._options = options; this._notReadyCommandsQueue = []; this._runningCommands = new _Set(); @@ -52,16 +55,16 @@ export default class RedisAdapter extends ioredis { _listenToEvents() { this.once('ready', () => { const commandsCount = this._notReadyCommandsQueue ? this._notReadyCommandsQueue.length : 0; - log.i(`Redis connection established. Queued commands: ${commandsCount}.`); + this.log.i(`Redis connection established. Queued commands: ${commandsCount}.`); this._notReadyCommandsQueue && this._notReadyCommandsQueue.forEach(queued => { - log.i(`Executing queued ${queued.name} command.`); + this.log.i(`Executing queued ${queued.name} command.`); queued.command().then(queued.resolve).catch(queued.reject); }); // After the SDK is ready for the first time we'll stop queueing commands. This is just so we can keep handling BUR for them. this._notReadyCommandsQueue = undefined; }); this.once('close', () => { - log.i('Redis connection closed.'); + this.log.i('Redis connection closed.'); }); } @@ -75,7 +78,7 @@ export default class RedisAdapter extends ioredis { const params = arguments; function commandWrapper() { - log.d(`Executing ${method}.`); + instance.log.d(`Executing ${method}.`); // Return original method const result = originalMethod.apply(instance, params); @@ -90,7 +93,7 @@ export default class RedisAdapter extends ioredis { result.then(cleanUpRunningCommandsCb, cleanUpRunningCommandsCb); return timeout(instance._options.operationTimeout, result).catch(err => { - log.e(`${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`); + instance.log.e(`${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`); // Handling is not the adapter responsibility. throw err; }); @@ -123,19 +126,19 @@ export default class RedisAdapter extends ioredis { setTimeout(function deferedDisconnect() { if (instance._runningCommands.size > 0) { - log.i(`Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`); + instance.log.i(`Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`); Promise.all(setToArray(instance._runningCommands)) .then(() => { - log.d('Pending commands finished successfully, disconnecting.'); + instance.log.d('Pending commands finished successfully, disconnecting.'); originalMethod.apply(instance, params); }) .catch(e => { - log.w(`Pending commands finished with error: ${e}. Proceeding with disconnection.`); + instance.log.w(`Pending commands finished with error: ${e}. Proceeding with disconnection.`); originalMethod.apply(instance, params); }); } else { - log.d('No commands pending execution, disconnect.'); + instance.log.d('No commands pending execution, disconnect.'); // Nothing pending, just proceed. originalMethod.apply(instance, params); } diff --git a/src/storages/inRedis/SplitsCacheInRedis.ts b/src/storages/inRedis/SplitsCacheInRedis.ts index 5bfc8bd4..2a65900a 100644 --- a/src/storages/inRedis/SplitsCacheInRedis.ts +++ b/src/storages/inRedis/SplitsCacheInRedis.ts @@ -1,9 +1,10 @@ import { isFiniteNumber, isNaNNumber } from '../../utils/lang'; import KeyBuilderSS from '../KeyBuilderSS'; import { ISplitsCacheAsync } from '../types'; -import { logFactory } from '../../logger/sdkLogger'; import { Redis } from 'ioredis'; -const log = logFactory('splitio-storage:redis'); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-storage:redis'); /** * Discard errors for an answer of multiple operations. @@ -25,7 +26,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { private readonly keys: KeyBuilderSS; private redisError?: string; - constructor(keys: KeyBuilderSS, redis: Redis) { + constructor(private readonly log: ILogger, keys: KeyBuilderSS, redis: Redis) { this.redis = redis; this.keys = keys; @@ -82,7 +83,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { */ getSplit(name: string): Promise { if (this.redisError) { - log.e(this.redisError); + this.log.e(this.redisError); throw this.redisError; } @@ -136,14 +137,14 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { .then((ttCount: string | null | number) => { ttCount = parseInt(ttCount as string, 10); if (!isFiniteNumber(ttCount) || ttCount < 0) { - log.i(`Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`); + this.log.i(`Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`); return false; } return ttCount > 0; }) .catch(e => { - log.e(`Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`); + this.log.e(`Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`); // If there is an error, bypass the validation so the event can get tracked. return true; }); @@ -168,7 +169,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { */ getSplits(names: string[]): Promise> { if (this.redisError) { - log.e(this.redisError); + this.log.e(this.redisError); throw this.redisError; } @@ -182,7 +183,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { return Promise.resolve(splits); }) .catch(e => { - log.e(`Could not grab splits due to an error: ${e}.`); + this.log.e(`Could not grab splits due to an error: ${e}.`); return Promise.reject(e); }); } diff --git a/src/storages/inRedis/index.ts b/src/storages/inRedis/index.ts index f3330f38..9b764c68 100644 --- a/src/storages/inRedis/index.ts +++ b/src/storages/inRedis/index.ts @@ -34,9 +34,10 @@ export function InRedisStorage(options: InRedisStorageOptions = {}) { return function InRedisStorageFactory(params: IStorageFactoryParams): IStorageAsync { + const log = params.log; const metadata = metadataBuilder(params.metadata); const keys = new KeyBuilderSS(prefix, { version: metadata.s, ip: metadata.i, hostname: metadata.n }); - const redisClient = new RedisAdapter(options.options || {}); + const redisClient = new RedisAdapter(log, options.options || {}); // subscription to Redis connect event in order to emit SDK_READY event // @TODO pass a callback to simplify custom storages @@ -46,10 +47,10 @@ export function InRedisStorage(options: InRedisStorageOptions = {}) { }); return { - splits: new SplitsCacheInRedis(keys, redisClient), + splits: new SplitsCacheInRedis(log, keys, redisClient), segments: new SegmentsCacheInRedis(keys, redisClient), impressions: new ImpressionsCacheInRedis(keys, redisClient, metadata), - events: new EventsCacheInRedis(keys, redisClient, metadata), + events: new EventsCacheInRedis(log, keys, redisClient, metadata), latencies: new LatenciesCacheInRedis(keys, redisClient), counts: new CountsCacheInRedis(keys, redisClient), diff --git a/src/storages/types.ts b/src/storages/types.ts index 2925e7cc..f9626ea6 100644 --- a/src/storages/types.ts +++ b/src/storages/types.ts @@ -1,4 +1,5 @@ import { MaybeThenable, IMetadata, ISplitFiltersValidation } from '../dtos/types'; +import { ILogger } from '../logger/types'; import { IReadinessManager } from '../readiness/types'; import { SplitIO, ImpressionDTO } from '../types'; @@ -246,5 +247,6 @@ export interface IStorageFactoryParams { // ATM, only used by InRedisStorage. @TODO pass a callback to simplify custom storages. readinessManager: IReadinessManager, - metadata: IMetadata + metadata: IMetadata, + log: ILogger } diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index 75390064..94a65654 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -4,12 +4,13 @@ import fs from 'fs'; import path from 'path'; // @ts-ignore import yaml from 'js-yaml'; -import { logFactory } from '../../../logger/sdkLogger'; import { isString, endsWith, find, forOwn, uniq, } from '../../../utils/lang'; import parseCondition, { IMockSplitEntry } from './parseCondition'; import { ISplitPartial } from '../../../dtos/types'; import { SplitIO } from '../../../types'; -const log = logFactory('splitio-offline:splits-fetcher'); +import { ILogger } from '../../../logger/types'; +// import { logFactory } from '../../../logger/sdkLogger'; +// const log = logFactory('splitio-offline:splits-fetcher'); type IYamlSplitEntry = Record @@ -39,7 +40,7 @@ function configFilesPath(configFilePath?: SplitIO.MockedFeaturesFilePath): Split } // Parse `.split` configuration file and return a map of "Split Objects" -function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath): false | Record { +function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILogger): false | Record { const SPLIT_POSITION = 0; const TREATMENT_POSITION = 1; let data; @@ -79,7 +80,7 @@ function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath): false | } // Parse `.yml` or `.yaml` configuration files and return a map of "Split Objects" -function readYAMLConfigFile(filePath: SplitIO.MockedFeaturesFilePath): false | Record { +function readYAMLConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILogger): false | Record { let data = ''; let yamldoc = null; @@ -160,16 +161,16 @@ function arrangeConditions(mocksData: Record & { } // Load the content of a configuration file into an Object -export default function splitsParserFromFile(settings: { features?: SplitIO.MockedFeaturesFilePath }): false | Record { - const filePath = configFilesPath(settings.features); +export default function splitsParserFromFile({ features, log }: { features?: SplitIO.MockedFeaturesFilePath, log: ILogger }): false | Record { + const filePath = configFilesPath(features); let mockData: false | Record; // If we have a filePath, it means the extension is correct, choose the parser. if (endsWith(filePath, '.split')) { log.w('.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'); - mockData = readSplitConfigFile(filePath); + mockData = readSplitConfigFile(filePath, log); } else { - mockData = readYAMLConfigFile(filePath); + mockData = readYAMLConfigFile(filePath, log); } return mockData; diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index d5a1f813..ef27ac78 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -1,5 +1,4 @@ import { forOwn } from '../../../utils/lang'; -import { logFactory } from '../../../logger/sdkLogger'; import { IReadinessManager } from '../../../readiness/types'; import { ISplitsCacheSync } from '../../../storages/types'; import { ISplitsParser } from '../splitsParser/types'; @@ -8,7 +7,8 @@ import syncTaskFactory from '../../syncTask'; import { ISyncTask } from '../../types'; import { ISettings } from '../../../types'; import { CONTROL } from '../../../utils/constants'; -const log = logFactory('splitio-producer:offline'); +// import { logFactory } from '../../../logger/sdkLogger'; +// const log = logFactory('splitio-producer:offline'); /** * Offline equivalent of `splitChangesUpdaterFactory` @@ -20,6 +20,8 @@ export function fromObjectUpdaterFactory( settings: ISettings, ): () => Promise { + const log = settings.log; + return function objectUpdater() { const splits: [string, string][] = []; let loadError = null; @@ -82,6 +84,7 @@ export default function fromObjectSyncTaskFactory( settings, ), settings.scheduler.offlineRefreshRate, - 'offlineUpdater' + 'offlineUpdater', + settings.log ); } diff --git a/src/sync/polling/pollingManagerCS.ts b/src/sync/polling/pollingManagerCS.ts index 00b8be67..1dc0c7b0 100644 --- a/src/sync/polling/pollingManagerCS.ts +++ b/src/sync/polling/pollingManagerCS.ts @@ -1,5 +1,4 @@ import { ISegmentsSyncTask, ISplitsSyncTask, IPollingManagerCS } from './types'; -import { logFactory } from '../../logger/sdkLogger'; import { forOwn } from '../../utils/lang'; import { IReadinessManager } from '../../readiness/types'; import { ISplitApi } from '../../services/types'; @@ -8,7 +7,8 @@ import mySegmentsSyncTaskFactory from './syncTasks/mySegmentsSyncTask'; import splitsSyncTaskFactory from './syncTasks/splitsSyncTask'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; -const log = logFactory('splitio-sync:polling-manager'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:polling-manager'); /** * Expose start / stop mechanism for polling data from services. @@ -21,6 +21,8 @@ export default function pollingManagerCSFactory( settings: ISettings, ): IPollingManagerCS { + const log = settings.log; + const splitsSyncTask: ISplitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings); // Map of matching keys to their corresponding MySegmentsSyncTask. diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index ca30fe66..4ab0aab5 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -5,9 +5,9 @@ import { IReadinessManager } from '../../readiness/types'; import { ISplitApi } from '../../services/types'; import { ISettings } from '../../types'; import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types'; -import { logFactory } from '../../logger/sdkLogger'; import thenable from '../../utils/promise/thenable'; -const log = logFactory('splitio-sync:polling-manager'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:polling-manager'); /** * Expose start / stop mechanism for pulling data from services. @@ -19,6 +19,8 @@ export default function pollingManagerSSFactory( settings: ISettings ): IPollingManager { + const log = settings.log; + const splitsSyncTask: ISplitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings); const segmentsSyncTask: ISegmentsSyncTask = segmentsSyncTaskFactory(splitApi.fetchSegmentChanges, storage, readiness, settings); diff --git a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts index db76608d..3ff393e4 100644 --- a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts @@ -5,12 +5,12 @@ import { SplitError } from '../../../utils/lang/errors'; import timeout from '../../../utils/promise/timeout'; import syncTaskFactory from '../../syncTask'; import { ISegmentsSyncTask } from '../types'; - -import { logFactory } from '../../../logger/sdkLogger'; import { IFetchMySegments } from '../../../services/types'; import mySegmentsFetcherFactory from '../fetchers/mySegmentsFetcher'; import { ISettings } from '../../../types'; -const log = logFactory('splitio-sync:my-segments'); +import { ILogger } from '../../../logger/types'; +// import { logFactory } from '../../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:my-segments'); type IMySegmentsUpdater = (segmentList?: string[]) => Promise @@ -26,7 +26,8 @@ function mySegmentsUpdaterFactory( mySegmentsCache: ISegmentsCacheSync, segmentsEventEmitter: ISegmentsEventEmitter, requestTimeoutBeforeReady: number, - retriesOnFailureBeforeReady: number + retriesOnFailureBeforeReady: number, + log: ILogger ): IMySegmentsUpdater { let readyOnAlreadyExistentState = true; @@ -108,9 +109,11 @@ export default function mySegmentsSyncTaskFactory( storage.segments, readiness.segments, settings.startup.requestTimeoutBeforeReady, - settings.startup.retriesOnFailureBeforeReady + settings.startup.retriesOnFailureBeforeReady, + settings.log ), settings.scheduler.segmentsRefreshRate, - 'mySegmentsUpdater' + 'mySegmentsUpdater', + settings.log ); } diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index b1eb09f6..906ce181 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -6,12 +6,13 @@ import { findIndex } from '../../../utils/lang'; import { SplitError } from '../../../utils/lang/errors'; import syncTaskFactory from '../../syncTask'; import { ISegmentsSyncTask } from '../types'; -import { logFactory } from '../../../logger/sdkLogger'; import segmentChangesFetcherFactory from '../fetchers/segmentChangesFetcher'; import { IFetchSegmentChanges } from '../../../services/types'; import { ISettings } from '../../../types'; -const log = logFactory('splitio-sync:segment-changes'); -const inputValidationLog = logFactory('', { displayAllErrors: true }); +import { ILogger } from '../../../logger/types'; +// import { logFactory } from '../../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:segment-changes'); +// const inputValidationLog = logFactory('', { displayAllErrors: true }); type ISegmentChangesUpdater = (segmentNames?: string[]) => Promise @@ -24,7 +25,8 @@ type ISegmentChangesUpdater = (segmentNames?: string[]) => Promise function segmentChangesUpdaterFactory( segmentChangesFetcher: ISegmentChangesFetcher, segmentsCache: ISegmentsCacheSync, - readiness: IReadinessManager + readiness: IReadinessManager, + log: ILogger ): ISegmentChangesUpdater { let readyOnAlreadyExistentState = true; @@ -92,7 +94,7 @@ function segmentChangesUpdaterFactory( if (error.statusCode === 403) { // @TODO although factory status is destroyed, synchronization is not stopped readiness.destroy(); - inputValidationLog.e('Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'); + log.e('Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'); } return false; @@ -111,9 +113,11 @@ export default function segmentsSyncTaskFactory( segmentChangesUpdaterFactory( segmentChangesFetcherFactory(fetchSegmentChanges), storage.segments, - readiness + readiness, + settings.log ), settings.scheduler.segmentsRefreshRate, - 'segmentChangesUpdater' + 'segmentChangesUpdater', + settings.log ); } diff --git a/src/sync/polling/syncTasks/splitsSyncTask.ts b/src/sync/polling/syncTasks/splitsSyncTask.ts index 5ae62252..ce3fb1dc 100644 --- a/src/sync/polling/syncTasks/splitsSyncTask.ts +++ b/src/sync/polling/syncTasks/splitsSyncTask.ts @@ -7,12 +7,13 @@ import { IReadinessManager, ISplitsEventEmitter } from '../../../readiness/types import timeout from '../../../utils/promise/timeout'; import syncTaskFactory from '../../syncTask'; import { ISplitsSyncTask } from '../types'; -import { logFactory } from '../../../logger/sdkLogger'; import splitChangesFetcherFactory from '../fetchers/splitChangesFetcher'; import { IFetchSplitChanges } from '../../../services/types'; import thenable from '../../../utils/promise/thenable'; import { ISettings } from '../../../types'; -const log = logFactory('splitio-sync:split-changes'); +import { ILogger } from '../../../logger/types'; +// import { logFactory } from '../../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:split-changes'); type ISplitChangesUpdater = () => Promise @@ -79,8 +80,9 @@ export function splitChangesUpdaterFactory( splitsCache: ISplitsCacheSync, segmentsCache: ISegmentsCacheSync, splitsEventEmitter: ISplitsEventEmitter, - requestTimeoutBeforeReady?: number, - retriesOnFailureBeforeReady?: number + requestTimeoutBeforeReady: number, + retriesOnFailureBeforeReady: number, + log: ILogger ): ISplitChangesUpdater { let startingUp = true; @@ -178,9 +180,11 @@ export default function splitsSyncTaskFactory( storage.segments, readiness.splits, settings.startup.requestTimeoutBeforeReady, - settings.startup.retriesOnFailureBeforeReady + settings.startup.retriesOnFailureBeforeReady, + settings.log, ), settings.scheduler.featuresRefreshRate, - 'splitChangesUpdater' + 'splitChangesUpdater', + settings.log ); } diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index 49d20c1a..f3699f5a 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -1,18 +1,19 @@ import { errorParser, messageParser } from './NotificationParser'; import notificationKeeperFactory from './NotificationKeeper'; import { OCCUPANCY, CONTROL, MY_SEGMENTS_UPDATE, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, SSE_ERROR } from '../constants'; -import { logFactory } from '../../../logger/sdkLogger'; import { IPushEventEmitter } from '../types'; import { ISseEventHandler } from '../SSEClient/types'; import { INotificationError } from './types'; -const log = logFactory('splitio-sync:sse-handler'); +import { ILogger } from '../../../logger/types'; +// import { logFactory } from '../../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:sse-handler'); /** * Factory for SSEHandler, which processes SSEClient messages and emits the corresponding push events. * * @param pushEmitter emitter for events related to streaming support */ -export default function SSEHandlerFactory(pushEmitter: IPushEventEmitter): ISseEventHandler { +export default function SSEHandlerFactory(pushEmitter: IPushEventEmitter, log: ILogger): ISseEventHandler { const notificationKeeper = notificationKeeperFactory(pushEmitter); diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index c7203b41..b6f3e501 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -12,15 +12,14 @@ import SegmentsUpdateWorker from './UpdateWorkers/SegmentsUpdateWorker'; import SplitsUpdateWorker from './UpdateWorkers/SplitsUpdateWorker'; import { authenticateFactory, hashUserKey } from './AuthClient'; import { forOwn } from '../../utils/lang'; -import { logFactory } from '../../logger/sdkLogger'; import SSEClient from './SSEClient'; import { IFetchAuth } from '../../services/types'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { MY_SEGMENTS_UPDATE, PUSH_DISABLED, PUSH_DISCONNECT, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, SSE_ERROR } from './constants'; import { IPlatform } from '../../sdkFactory/types'; - -const log = logFactory('splitio-sync:push-manager'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:push-manager'); /** * PushManager factory: @@ -36,6 +35,8 @@ export default function pushManagerFactory( settings: ISettings, ): IPushManagerCS | undefined { + const log = settings.log; + let sseClient: ISSEClient; try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); @@ -47,7 +48,7 @@ export default function pushManagerFactory( // init feedback loop const pushEmitter = new platform.EventEmitter() as IPushEventEmitter; - const sseHandler = SSEHandlerFactory(pushEmitter); + const sseHandler = SSEHandlerFactory(pushEmitter, log); sseClient.setEventHandler(sseHandler); // [Only for client-side] map of hashes to user keys, to dispatch MY_SEGMENTS_UPDATE events to the corresponding MySegmentsUpdateWorker diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index bbb6040f..a669f961 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -12,14 +12,13 @@ import MySegmentsUpdateWorker from './UpdateWorkers/MySegmentsUpdateWorker'; import SplitsUpdateWorker from './UpdateWorkers/SplitsUpdateWorker'; import { authenticateFactory, hashUserKey } from './AuthClient'; import { forOwn } from '../../utils/lang'; -import { logFactory } from '../../logger/sdkLogger'; import SSEClient from './SSEClient'; import { IFetchAuth } from '../../services/types'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { IPlatform } from '../../sdkFactory/types'; - -const log = logFactory('splitio-sync:push-manager'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:push-manager'); /** * PushManager factory for client-side, with support for multiple clients. @@ -34,6 +33,8 @@ export default function pushManagerCSFactory( settings: ISettings ): IPushManagerCS | undefined { + const log = settings.log; + let sseClient: ISSEClient; try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); @@ -45,7 +46,7 @@ export default function pushManagerCSFactory( // init feedback loop const pushEmitter = new platform.EventEmitter() as IPushEventEmitter; - const sseHandler = SSEHandlerFactory(pushEmitter); + const sseHandler = SSEHandlerFactory(pushEmitter, log); sseClient.setEventHandler(sseHandler); // [Only for client-side] map of hashes to user keys, to dispatch MY_SEGMENTS_UPDATE events to the corresponding MySegmentsUpdateWorker diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index 324f3cde..f2ba56c8 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -9,14 +9,13 @@ import Backoff from '../../utils/Backoff'; import SSEHandlerFactory from './SSEHandler'; import SegmentsUpdateWorker from './UpdateWorkers/SegmentsUpdateWorker'; import SplitsUpdateWorker from './UpdateWorkers/SplitsUpdateWorker'; -import { logFactory } from '../../logger/sdkLogger'; import { IFetchAuth } from '../../services/types'; import { authenticateFactory } from './AuthClient'; import SSEClient from './SSEClient'; import { ISettings } from '../../types'; import { IPlatform } from '../../sdkFactory/types'; - -const log = logFactory('splitio-sync:push-manager'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:push-manager'); /** * PushManager factory for server-side @@ -30,6 +29,8 @@ export default function pushManagerSSFactory( settings: ISettings ): IPushManager | undefined { + const log = settings.log; + let sseClient: ISSEClient; try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); @@ -41,7 +42,7 @@ export default function pushManagerSSFactory( // init feedback loop (pushEmitter) const pushEmitter = new platform.EventEmitter() as IPushEventEmitter; - const sseHandler = SSEHandlerFactory(pushEmitter); + const sseHandler = SSEHandlerFactory(pushEmitter, log); sseClient.setEventHandler(sseHandler); // init workers diff --git a/src/sync/submitters/eventsSyncTask.ts b/src/sync/submitters/eventsSyncTask.ts index 19c7fe85..d0d3d235 100644 --- a/src/sync/submitters/eventsSyncTask.ts +++ b/src/sync/submitters/eventsSyncTask.ts @@ -2,8 +2,9 @@ import { IEventsCacheSync } from '../../storages/types'; import { IPostEventsBulk } from '../../services/types'; import { ISyncTask, ITimeTracker } from '../types'; import { submitterSyncTaskFactory } from './submitterSyncTask'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-sync:submitters'); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:submitters'); /** * Sync task that periodically posts tracked events @@ -13,11 +14,12 @@ export function eventsSyncTaskFactory( eventsCache: IEventsCacheSync, eventsPushRate: number, eventsFirstPushWindow: number, + log: ILogger, latencyTracker?: ITimeTracker ): ISyncTask { // don't retry events. - const syncTask = submitterSyncTaskFactory(postEventsBulk, eventsCache, eventsPushRate, 'queued events', latencyTracker); + const syncTask = submitterSyncTaskFactory(postEventsBulk, eventsCache, eventsPushRate, 'queued events', log, latencyTracker); // Set a timer for the first push of events, if (eventsFirstPushWindow > 0) { diff --git a/src/sync/submitters/impressionCountsSyncTask.ts b/src/sync/submitters/impressionCountsSyncTask.ts index 2e5534c1..c489bca1 100644 --- a/src/sync/submitters/impressionCountsSyncTask.ts +++ b/src/sync/submitters/impressionCountsSyncTask.ts @@ -3,6 +3,7 @@ import { IPostTestImpressionsCount } from '../../services/types'; import { IImpressionCountsCacheSync } from '../../storages/types'; import { submitterSyncTaskFactory } from './submitterSyncTask'; import { ImpressionCountsPayload } from './types'; +import { ILogger } from '../../logger/types'; /** * Converts `impressionCounts` data from cache into request payload. @@ -36,9 +37,10 @@ const IMPRESSIONS_COUNT_RATE = 1800000; // 30 minutes export function impressionCountsSyncTaskFactory( postTestImpressionsCount: IPostTestImpressionsCount, impressionCountsCache: IImpressionCountsCacheSync, + log: ILogger, latencyTracker?: ITimeTracker ): ISyncTask { // retry impressions counts only once. - return submitterSyncTaskFactory(postTestImpressionsCount, impressionCountsCache, IMPRESSIONS_COUNT_RATE, 'impression counts', latencyTracker, fromImpressionCountsCollector, 1); + return submitterSyncTaskFactory(postTestImpressionsCount, impressionCountsCache, IMPRESSIONS_COUNT_RATE, 'impression counts', log, latencyTracker, fromImpressionCountsCollector, 1); } diff --git a/src/sync/submitters/impressionsSyncTask.ts b/src/sync/submitters/impressionsSyncTask.ts index 715e00e0..fd4b20b8 100644 --- a/src/sync/submitters/impressionsSyncTask.ts +++ b/src/sync/submitters/impressionsSyncTask.ts @@ -5,6 +5,7 @@ import { IImpressionsCacheSync } from '../../storages/types'; import { ImpressionDTO } from '../../types'; import { submitterSyncTaskFactory } from './submitterSyncTask'; import { ImpressionsPayload } from './types'; +import { ILogger } from '../../logger/types'; /** * Converts `impressions` data from cache into request payload. @@ -44,9 +45,10 @@ export function impressionsSyncTaskFactory( impressionsCache: IImpressionsCacheSync, impressionsRefreshRate: number, sendLabels = false, + log: ILogger, latencyTracker?: ITimeTracker, ): ISyncTask { // retry impressions only once. - return submitterSyncTaskFactory(postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, 'impressions', latencyTracker, fromImpressionsCollector.bind(undefined, sendLabels), 1); + return submitterSyncTaskFactory(postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, 'impressions', log, latencyTracker, fromImpressionsCollector.bind(undefined, sendLabels), 1); } diff --git a/src/sync/submitters/metricsSyncTask.ts b/src/sync/submitters/metricsSyncTask.ts index 600d247c..6f1cf4ad 100644 --- a/src/sync/submitters/metricsSyncTask.ts +++ b/src/sync/submitters/metricsSyncTask.ts @@ -4,6 +4,7 @@ import { ICountsCacheSync, ILatenciesCacheSync } from '../../storages/types'; import { IPostMetricsCounters, IPostMetricsTimes } from '../../services/types'; import { ISyncTask, ITimeTracker } from '../types'; import { submitterSyncTaskFactory } from './submitterSyncTask'; +import { ILogger } from '../../logger/types'; // extract POST payload object from cache function fromCache(propertyName: 'latencies' | 'delta') { @@ -25,10 +26,11 @@ export function countsSyncTaskFactory( postMetricsCounters: IPostMetricsCounters, countsCache: ICountsCacheSync, metricsRefreshRate: number, + log: ILogger, latencyTracker?: ITimeTracker ): ISyncTask { - return submitterSyncTaskFactory(postMetricsCounters, countsCache, metricsRefreshRate, 'count metrics', latencyTracker, fromCache('delta')); + return submitterSyncTaskFactory(postMetricsCounters, countsCache, metricsRefreshRate, 'count metrics', log, latencyTracker, fromCache('delta')); } /** @@ -38,9 +40,10 @@ export function latenciesSyncTaskFactory( postMetricsLatencies: IPostMetricsTimes, latenciesCache: ILatenciesCacheSync, metricsRefreshRate: number, + log: ILogger, latencyTracker?: ITimeTracker ): ISyncTask { // don't retry metrics. - return submitterSyncTaskFactory(postMetricsLatencies, latenciesCache, metricsRefreshRate, 'latency metrics', latencyTracker, fromCache('latencies')); + return submitterSyncTaskFactory(postMetricsLatencies, latenciesCache, metricsRefreshRate, 'latency metrics', log, latencyTracker, fromCache('latencies')); } diff --git a/src/sync/submitters/submitterSyncTask.ts b/src/sync/submitters/submitterSyncTask.ts index 4a5acbcc..3a087954 100644 --- a/src/sync/submitters/submitterSyncTask.ts +++ b/src/sync/submitters/submitterSyncTask.ts @@ -1,8 +1,9 @@ import syncTaskFactory from '../syncTask'; -import { logFactory } from '../../logger/sdkLogger'; import { ISyncTask, ITimeTracker } from '../types'; import { IRecorderCacheConsumerSync } from '../../storages/types'; -const log = logFactory('splitio-sync:submitters'); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-sync:submitters'); /** * Base function to create submitter sync tasks, such as ImpressionsSyncTask and EventsSyncTask @@ -12,6 +13,7 @@ export function submitterSyncTaskFactory( sourceCache: IRecorderCacheConsumerSync, postRate: number, dataName: string, + log: ILogger, latencyTracker?: ITimeTracker, fromCacheToPayload?: (cacheData: TState) => any, maxRetries: number = 0, @@ -51,5 +53,5 @@ export function submitterSyncTaskFactory( return latencyTrackerStop ? postPromise.then(latencyTrackerStop).catch(latencyTrackerStop) : postPromise; } - return syncTaskFactory(postData, postRate, dataName + ' submitter'); + return syncTaskFactory(postData, postRate, dataName + ' submitter', log); } diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index 3b32e515..72a94c22 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -7,9 +7,9 @@ import { IReadinessManager } from '../readiness/types'; import { IStorageSync } from '../storages/types'; import { IPushManagerFactoryParams, IPushManager, IPushManagerCS } from './streaming/types'; import { IPollingManager, IPollingManagerCS, IPollingManagerFactoryParams } from './polling/types'; -import { logFactory } from '../logger/sdkLogger'; import { PUSH_CONNECT, PUSH_DISCONNECT } from './streaming/constants'; -export const log = logFactory('splitio-sync:sync-manager'); +// import { logFactory } from '../logger/sdkLogger'; +// export const log = logFactory('splitio-sync:sync-manager'); /** * Online SyncManager factory. @@ -35,6 +35,8 @@ export function syncManagerOnlineFactory( readiness }: ISyncManagerFactoryParams): ISyncManagerCS { + const log = settings.log; + /** Polling Manager */ const pollingManager = pollingManagerFactory(splitApi, storage, readiness, settings); @@ -46,11 +48,11 @@ export function syncManagerOnlineFactory( /** Submitter Manager */ // It is not inyected via a factory as push and polling managers, because at the moment it is mandatory and the same for server-side and client-side variants const submitters = [ - impressionsSyncTaskFactory(splitApi.postTestImpressionsBulk, storage.impressions, settings.scheduler.impressionsRefreshRate, settings.core.labelsEnabled), - eventsSyncTaskFactory(splitApi.postEventsBulk, storage.events, settings.scheduler.eventsPushRate, settings.startup.eventsFirstPushWindow) + impressionsSyncTaskFactory(splitApi.postTestImpressionsBulk, storage.impressions, settings.scheduler.impressionsRefreshRate, settings.core.labelsEnabled, log), + eventsSyncTaskFactory(splitApi.postEventsBulk, storage.events, settings.scheduler.eventsPushRate, settings.startup.eventsFirstPushWindow, log) // @TODO add telemetry submitter ]; - if (storage.impressionCounts) submitters.push(impressionCountsSyncTaskFactory(splitApi.postTestImpressionsCount, storage.impressionCounts)); + if (storage.impressionCounts) submitters.push(impressionCountsSyncTaskFactory(splitApi.postTestImpressionsCount, storage.impressionCounts, log)); const submitter = syncTaskComposite(submitters); diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index 3487dd69..8b8dc3a2 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -1,11 +1,12 @@ -import { logFactory } from '../logger/sdkLogger'; +import { ILogger } from '../logger/types'; import { ISyncTask } from './types'; -const log = logFactory('splitio-sync:task'); +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio-sync:task'); /** * factory of sync tasks */ -export default function syncTaskFactory(task: (...args: Input) => Promise, period: number, taskName = 'task'): ISyncTask { +export default function syncTaskFactory(task: (...args: Input) => Promise, period: number, taskName = 'task', log: ILogger): ISyncTask { // flag that indicates if the task is being executed let executing = false; diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index d49514b2..9c533f3d 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -1,10 +1,11 @@ import objectAssign from 'object-assign'; import thenable from '../utils/promise/thenable'; -import { logFactory } from '../logger/sdkLogger'; import { IEventsCacheBase } from '../storages/types'; import { IEventsHandler, IEventTracker } from './types'; import { SplitIO } from '../types'; -const log = logFactory('splitio-client:event-tracker'); +import { ILogger } from '../logger/types'; +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio-client:event-tracker'); /** * Event tracker stores events in cache and pass them to the integrations manager if provided. @@ -13,6 +14,7 @@ const log = logFactory('splitio-client:event-tracker'); * @param integrationsManager optional event handler used for integrations */ export default function eventTrackerFactory( + log: ILogger, eventsCache: IEventsCacheBase, integrationsManager?: IEventsHandler ): IEventTracker { diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index a35694cc..9c48a4d3 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -1,13 +1,14 @@ import objectAssign from 'object-assign'; import thenable from '../utils/promise/thenable'; import { truncateTimeFrame } from '../utils/time'; -import { logFactory } from '../logger/sdkLogger'; import { IImpressionCountsCacheBase, IImpressionsCacheBase } from '../storages/types'; import { IImpressionsHandler, IImpressionsTracker } from './types'; import { IMetadata } from '../dtos/types'; import { SplitIO, ImpressionDTO } from '../types'; import { IImpressionObserver } from './impressionObserver/types'; -const log = logFactory('splitio-client:impressions-tracker'); +import { ILogger } from '../logger/types'; +// import { logFactory } from '../logger/sdkLogger'; +// const log = logFactory('splitio-client:impressions-tracker'); /** * Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided. @@ -20,6 +21,7 @@ const log = logFactory('splitio-client:impressions-tracker'); * @param countsCache optional cache to save impressions count. If provided, impressions will be deduped (OPTIMIZED mode) */ export default function impressionsTrackerFactory( + log: ILogger, impressionsCache: IImpressionsCacheBase, // @TODO consider passing only an optional integrationsManager to handle impressions diff --git a/src/types.ts b/src/types.ts index a10a82b6..c2093371 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,5 @@ import { IIntegration, IIntegrationFactoryParams } from './integrations/types'; +import { ILogger } from './logger/types'; /* eslint-disable no-use-before-define */ import { IStorageFactoryParams, IStorageSyncCS, IStorageSync, IStorageAsync } from './storages/types'; @@ -100,7 +101,8 @@ export interface ISettings { readonly runtime: { ip: string | false hostname: string | false - } + }, + readonly log: ILogger } /** * Log levels. diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index 6b1e180b..b8d804e6 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -1,14 +1,15 @@ +import { ILogger } from '../../logger/types'; import { isString } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('', { - // Errors on API key validation are important enough so that one day we might force logging them or throw an exception on startup. - displayAllErrors: true -}); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('', { +// // Errors on API key validation are important enough so that one day we might force logging them or throw an exception on startup. +// displayAllErrors: true +// }); function apiKeyError(reason: string) { return `Factory instantiation: ${reason}, api_key must be a non-empty string.`; } /** validates the given api key */ -export function validateApiKey(maybeApiKey: any): string | false { +export function validateApiKey(log: ILogger, maybeApiKey: any): string | false { let apiKey: string | false = false; if (maybeApiKey == undefined) { // eslint-disable-line eqeqeq log.e(apiKeyError('you passed a null or undefined api_key')); @@ -29,8 +30,8 @@ const usedKeysMap: Record = {}; function apiKeyWarn(reason: string) { return `Factory instantiation: ${reason}. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.`; } /** validates the given api key and also warns if it is in use */ -export function validateAndTrackApiKey(maybeApiKey: any): string | false { - const apiKey = validateApiKey(maybeApiKey); +export function validateAndTrackApiKey(log: ILogger, maybeApiKey: any): string | false { + const apiKey = validateApiKey(log, maybeApiKey); // If the apiKey is correct, we'll save it as the instance creation should work. if (apiKey) { diff --git a/src/utils/inputValidation/attributes.ts b/src/utils/inputValidation/attributes.ts index 4a3a0c33..c2265810 100644 --- a/src/utils/inputValidation/attributes.ts +++ b/src/utils/inputValidation/attributes.ts @@ -1,9 +1,10 @@ import { isObject } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; import { SplitIO } from '../../types'; -const log = logFactory(''); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); -export function validateAttributes(maybeAttrs: any, method: string): SplitIO.Attributes | undefined | false { +export function validateAttributes(log: ILogger, maybeAttrs: any, method: string): SplitIO.Attributes | undefined | false { // Attributes are optional if (isObject(maybeAttrs) || maybeAttrs == undefined) // eslint-disable-line eqeqeq return maybeAttrs; diff --git a/src/utils/inputValidation/event.ts b/src/utils/inputValidation/event.ts index 0fc2d282..cb4b774c 100644 --- a/src/utils/inputValidation/event.ts +++ b/src/utils/inputValidation/event.ts @@ -1,10 +1,11 @@ +import { ILogger } from '../../logger/types'; import { isString } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory(''); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); const EVENT_TYPE_REGEX = /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/; -export function validateEvent(maybeEvent: any, method: string): string | false { +export function validateEvent(log: ILogger, maybeEvent: any, method: string): string | false { if (maybeEvent == undefined) { // eslint-disable-line eqeqeq log.e(`${method}: you passed a null or undefined event_type, event_type must be a non-empty string.`); } else if (!isString(maybeEvent)) { diff --git a/src/utils/inputValidation/eventProperties.ts b/src/utils/inputValidation/eventProperties.ts index f2d2390d..99051d72 100644 --- a/src/utils/inputValidation/eventProperties.ts +++ b/src/utils/inputValidation/eventProperties.ts @@ -1,7 +1,8 @@ import { isObject, shallowClone, isString, isFiniteNumber, isBoolean } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; import { SplitIO } from '../../types'; -const log = logFactory(''); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); const ECMA_SIZES = { NULL: 0, // While on the JSON it's going to occupy more space, we'll take it as 0 for the approximation. @@ -13,7 +14,7 @@ const MAX_PROPERTIES_AMOUNT = 300; const MAX_PROPERTIES_SIZE = 1024 * 32; const BASE_EVENT_SIZE = 1024; // We assume 1kb events without properties (avg measured) -export function validateEventProperties(maybeProperties: any, method: string): { properties: SplitIO.Properties | null | false, size: number } { +export function validateEventProperties(log: ILogger, maybeProperties: any, method: string): { properties: SplitIO.Properties | null | false, size: number } { if (maybeProperties == undefined) return { properties: null, size: BASE_EVENT_SIZE }; // eslint-disable-line eqeqeq if (!isObject(maybeProperties)) { diff --git a/src/utils/inputValidation/eventValue.ts b/src/utils/inputValidation/eventValue.ts index 13e7bb29..ef65b656 100644 --- a/src/utils/inputValidation/eventValue.ts +++ b/src/utils/inputValidation/eventValue.ts @@ -1,8 +1,9 @@ +import { ILogger } from '../../logger/types'; import { isFiniteNumber } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory(''); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); -export function validateEventValue(maybeValue: any, method: string): number | false { +export function validateEventValue(log: ILogger, maybeValue: any, method: string): number | false { if (isFiniteNumber(maybeValue) || maybeValue == undefined) // eslint-disable-line eqeqeq return maybeValue; diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index 5e8a77c7..f9028593 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -1,15 +1,16 @@ -import { logFactory } from '../../logger/sdkLogger'; +import { ILogger } from '../../logger/types'; import { IReadinessManager } from '../../readiness/types'; -const log = logFactory('', { displayAllErrors: true }); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('', { displayAllErrors: true }); -export function validateIfNotDestroyed(readinessManager: IReadinessManager): boolean { +export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadinessManager): boolean { if (!readinessManager.isDestroyed()) return true; log.e('Client has already been destroyed - no calls possible.'); return false; } -export function validateIfOperational(readinessManager: IReadinessManager, method: string) { +export function validateIfOperational(log: ILogger, readinessManager: IReadinessManager, method: string) { if (readinessManager.isReady() || readinessManager.isReadyFromCache()) return true; log.w(`${method}: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.`); diff --git a/src/utils/inputValidation/key.ts b/src/utils/inputValidation/key.ts index 535583cd..42059b07 100644 --- a/src/utils/inputValidation/key.ts +++ b/src/utils/inputValidation/key.ts @@ -1,11 +1,12 @@ import { isObject, isString, isFiniteNumber, toString } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; import { SplitIO } from '../../types'; -const log = logFactory(''); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); const KEY_MAX_LENGTH = 250; -function validateKeyValue(maybeKey: any, method: string, type: string): string | false { +function validateKeyValue(log: ILogger, maybeKey: any, method: string, type: string): string | false { if (maybeKey == undefined) { // eslint-disable-line eqeqeq log.e(`${method}: you passed a null or undefined ${type}, ${type} must be a non-empty string.`); return false; @@ -33,11 +34,11 @@ function validateKeyValue(maybeKey: any, method: string, type: string): string | return false; } -export function validateKey(maybeKey: any, method: string): SplitIO.SplitKey | false { +export function validateKey(log: ILogger, maybeKey: any, method: string): SplitIO.SplitKey | false { if (isObject(maybeKey)) { // Validate key object - const matchingKey = validateKeyValue(maybeKey.matchingKey, method, 'matchingKey'); - const bucketingKey = validateKeyValue(maybeKey.bucketingKey, method, 'bucketingKey'); + const matchingKey = validateKeyValue(log, maybeKey.matchingKey, method, 'matchingKey'); + const bucketingKey = validateKeyValue(log, maybeKey.bucketingKey, method, 'bucketingKey'); if (matchingKey && bucketingKey) return { matchingKey, bucketingKey @@ -46,6 +47,6 @@ export function validateKey(maybeKey: any, method: string): SplitIO.SplitKey | f log.e(`${method}: Key must be an object with bucketingKey and matchingKey with valid string properties.`); return false; } else { - return validateKeyValue(maybeKey, method, 'key'); + return validateKeyValue(log, maybeKey, method, 'key'); } } diff --git a/src/utils/inputValidation/preloadedData.ts b/src/utils/inputValidation/preloadedData.ts index a2432a90..769cc083 100644 --- a/src/utils/inputValidation/preloadedData.ts +++ b/src/utils/inputValidation/preloadedData.ts @@ -1,27 +1,28 @@ import { isObject, isString, isFiniteNumber } from '../lang'; import { validateSplit } from './split'; -import { logFactory } from '../../logger/sdkLogger'; import { SplitIO } from '../../types'; -const log = logFactory(''); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); -function validateTimestampData(maybeTimestamp: any, method: string, item: string) { +function validateTimestampData(log: ILogger, maybeTimestamp: any, method: string, item: string) { if (isFiniteNumber(maybeTimestamp) && maybeTimestamp > -1) return true; log.e(`${method}: preloadedData.${item} must be a positive number.`); return false; } -function validateSplitsData(maybeSplitsData: any, method: string) { +function validateSplitsData(log: ILogger, maybeSplitsData: any, method: string) { if (isObject(maybeSplitsData)) { const splitNames = Object.keys(maybeSplitsData); if (splitNames.length === 0) log.w(`${method}: preloadedData.splitsData doesn't contain split definitions.`); // @TODO in the future, consider handling the possibility of having parsed definitions of splits - if (splitNames.every(splitName => validateSplit(splitName, method) && isString(maybeSplitsData[splitName]))) return true; + if (splitNames.every(splitName => validateSplit(log, splitName, method) && isString(maybeSplitsData[splitName]))) return true; } log.e(`${method}: preloadedData.splitsData must be a map of split names to their serialized definitions.`); return false; } -function validateMySegmentsData(maybeMySegmentsData: any, method: string) { +function validateMySegmentsData(log: ILogger, maybeMySegmentsData: any, method: string) { if (isObject(maybeMySegmentsData)) { const userKeys = Object.keys(maybeMySegmentsData); if (userKeys.every(userKey => { @@ -34,7 +35,7 @@ function validateMySegmentsData(maybeMySegmentsData: any, method: string) { return false; } -function validateSegmentsData(maybeSegmentsData: any, method: string) { +function validateSegmentsData(log: ILogger, maybeSegmentsData: any, method: string) { if (isObject(maybeSegmentsData)) { const segmentNames = Object.keys(maybeSegmentsData); if (segmentNames.every(segmentName => isString(maybeSegmentsData[segmentName]))) return true; @@ -43,15 +44,15 @@ function validateSegmentsData(maybeSegmentsData: any, method: string) { return false; } -export function validatePreloadedData(maybePreloadedData: any, method: string): maybePreloadedData is SplitIO.PreloadedData { +export function validatePreloadedData(log: ILogger, maybePreloadedData: any, method: string): maybePreloadedData is SplitIO.PreloadedData { if (!isObject(maybePreloadedData)) { log.e(`${method}: preloadedData must be an object.`); } else if ( - validateTimestampData(maybePreloadedData.lastUpdated, method, 'lastUpdated') && - validateTimestampData(maybePreloadedData.since, method, 'since') && - validateSplitsData(maybePreloadedData.splitsData, method) && - (!maybePreloadedData.mySegmentsData || validateMySegmentsData(maybePreloadedData.mySegmentsData, method)) && - (!maybePreloadedData.segmentsData || validateSegmentsData(maybePreloadedData.segmentsData, method)) + validateTimestampData(log, maybePreloadedData.lastUpdated, method, 'lastUpdated') && + validateTimestampData(log, maybePreloadedData.since, method, 'since') && + validateSplitsData(log, maybePreloadedData.splitsData, method) && + (!maybePreloadedData.mySegmentsData || validateMySegmentsData(log, maybePreloadedData.mySegmentsData, method)) && + (!maybePreloadedData.segmentsData || validateSegmentsData(log, maybePreloadedData.segmentsData, method)) ) { return true; } diff --git a/src/utils/inputValidation/split.ts b/src/utils/inputValidation/split.ts index a4b7771c..ef5471dd 100644 --- a/src/utils/inputValidation/split.ts +++ b/src/utils/inputValidation/split.ts @@ -1,10 +1,12 @@ +import { ILogger } from '../../logger/types'; import { isString } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory(''); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); + // include BOM and nbsp const TRIMMABLE_SPACES_REGEX = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/; -export function validateSplit(maybeSplit: any, method: string, item = 'split name'): string | false { +export function validateSplit(log: ILogger, maybeSplit: any, method: string, item = 'split name'): string | false { if (maybeSplit == undefined) { // eslint-disable-line eqeqeq log.e(`${method}: you passed a null or undefined ${item}, ${item} must be a non-empty string.`); } else if (!isString(maybeSplit)) { diff --git a/src/utils/inputValidation/splitExistance.ts b/src/utils/inputValidation/splitExistance.ts index 1a92ff16..7b3bc616 100644 --- a/src/utils/inputValidation/splitExistance.ts +++ b/src/utils/inputValidation/splitExistance.ts @@ -1,13 +1,14 @@ import { SPLIT_NOT_FOUND } from '../labels'; import { IReadinessManager } from '../../readiness/types'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory(''); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); /** * This is defined here and in this format mostly because of the logger and the fact that it's considered a validation at product level. * But it's not going to run on the input validation layer. In any case, the most compeling reason to use it as we do is to avoid going to Redis and get a split twice. */ -export function validateSplitExistance(readinessManager: IReadinessManager, splitName: string, labelOrSplitObj: any, method: string): boolean { +export function validateSplitExistance(log: ILogger, readinessManager: IReadinessManager, splitName: string, labelOrSplitObj: any, method: string): boolean { if (readinessManager.isReady()) { // Only if it's ready we validate this, otherwise it may just be that the SDK is not ready yet. if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj == null) { log.w(`${method}: you passed "${splitName}" that does not exist in this environment, please double check what Splits exist in the web console.`); diff --git a/src/utils/inputValidation/splits.ts b/src/utils/inputValidation/splits.ts index 795ad01f..fb46528b 100644 --- a/src/utils/inputValidation/splits.ts +++ b/src/utils/inputValidation/splits.ts @@ -1,14 +1,15 @@ +import { ILogger } from '../../logger/types'; import { uniq } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; import { validateSplit } from './split'; -const log = logFactory(''); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); -export function validateSplits(maybeSplits: any, method: string, listName = 'split_names', item = 'split name'): string[] | false { +export function validateSplits(log: ILogger, maybeSplits: any, method: string, listName = 'split_names', item = 'split name'): string[] | false { if (Array.isArray(maybeSplits) && maybeSplits.length > 0) { let validatedArray: string[] = []; // Remove invalid values maybeSplits.forEach(maybeSplit => { - const splitName = validateSplit(maybeSplit, method, item); + const splitName = validateSplit(log, maybeSplit, method, item); if (splitName) validatedArray.push(splitName); }); diff --git a/src/utils/inputValidation/trafficType.ts b/src/utils/inputValidation/trafficType.ts index 9b46fd79..377569f0 100644 --- a/src/utils/inputValidation/trafficType.ts +++ b/src/utils/inputValidation/trafficType.ts @@ -1,10 +1,11 @@ +import { ILogger } from '../../logger/types'; import { isString } from '../lang'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory(''); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); const CAPITAL_LETTERS_REGEX = /[A-Z]/; -export function validateTrafficType(maybeTT: any, method: string): string | false { +export function validateTrafficType(log: ILogger, maybeTT: any, method: string): string | false { if (maybeTT == undefined) { // eslint-disable-line eqeqeq log.e(`${method}: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.`); } else if (!isString(maybeTT)) { diff --git a/src/utils/inputValidation/trafficTypeExistance.ts b/src/utils/inputValidation/trafficTypeExistance.ts index a7044b67..879dd0b6 100644 --- a/src/utils/inputValidation/trafficTypeExistance.ts +++ b/src/utils/inputValidation/trafficTypeExistance.ts @@ -1,20 +1,21 @@ import thenable from '../promise/thenable'; import { LOCALHOST_MODE } from '../constants'; -import { logFactory } from '../../logger/sdkLogger'; import { ISplitsCacheBase } from '../../storages/types'; import { IReadinessManager } from '../../readiness/types'; import { SDKMode } from '../../types'; import { MaybeThenable } from '../../dtos/types'; -const log = logFactory(''); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); -function logTTExistanceWarning(maybeTT: string, method: string) { +function logTTExistanceWarning(log: ILogger, maybeTT: string, method: string) { log.w(`${method}: Traffic Type ${maybeTT} does not have any corresponding Splits in this environment, make sure you're tracking your events to a valid traffic type defined in the Split console.`); } /** * Separated from the previous method since on some cases it'll be async. */ -export function validateTrafficTypeExistance(readinessManager: IReadinessManager, splitsCache: ISplitsCacheBase, mode: SDKMode, maybeTT: string, method: string): MaybeThenable { +export function validateTrafficTypeExistance(log: ILogger, readinessManager: IReadinessManager, splitsCache: ISplitsCacheBase, mode: SDKMode, maybeTT: string, method: string): MaybeThenable { // If not ready or in localhost mode, we won't run the validation if (!readinessManager.isReady() || mode === LOCALHOST_MODE) return true; @@ -23,12 +24,12 @@ export function validateTrafficTypeExistance(readinessManager: IReadinessManager if (thenable(res)) { res.then(function (isValid) { - if (!isValid) logTTExistanceWarning(maybeTT, method); + if (!isValid) logTTExistanceWarning(log, maybeTT, method); return isValid; // propagate result }); } else { - if (!res) logTTExistanceWarning(maybeTT, method); + if (!res) logTTExistanceWarning(log, maybeTT, method); } return res; diff --git a/src/utils/settingsValidation/__tests__/settings.mocks.ts b/src/utils/settingsValidation/__tests__/settings.mocks.ts index f803cfba..d3264707 100644 --- a/src/utils/settingsValidation/__tests__/settings.mocks.ts +++ b/src/utils/settingsValidation/__tests__/settings.mocks.ts @@ -1,5 +1,6 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS'; import { ISettings } from '../../../types'; +import { noopLogger } from '../../../logger/noopLogger'; export const settingsWithKey = { core: { @@ -76,7 +77,8 @@ export const fullSettings: ISettings = { sdk: 'sdk', auth: 'auth', streaming: 'streaming' - } + }, + log: noopLogger }; export const settingsSplitApi = { @@ -92,5 +94,6 @@ export const settingsSplitApi = { }, sync: { impressionsMode: 'DEBUG' - } + }, + log: noopLogger } as ISettings; diff --git a/src/utils/settingsValidation/impressionsMode.ts b/src/utils/settingsValidation/impressionsMode.ts index facff3e2..d927e179 100644 --- a/src/utils/settingsValidation/impressionsMode.ts +++ b/src/utils/settingsValidation/impressionsMode.ts @@ -1,9 +1,10 @@ +import { ILogger } from '../../logger/types'; import { SplitIO } from '../../types'; import { DEBUG, OPTIMIZED } from '../constants'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-settings'); +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-settings'); -export default function validImpressionsMode(impressionsMode: string): SplitIO.ImpressionsMode { +export default function validImpressionsMode(log: ILogger, impressionsMode: string): SplitIO.ImpressionsMode { impressionsMode = impressionsMode.toUpperCase(); if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) === -1) { log.e(`You passed an invalid impressionsMode, impressionsMode should be one of the following values: '${DEBUG}' or '${OPTIMIZED}'. Defaulting to '${OPTIMIZED}' mode.`); diff --git a/src/utils/settingsValidation/index.ts b/src/utils/settingsValidation/index.ts index 979720ea..655787b9 100644 --- a/src/utils/settingsValidation/index.ts +++ b/src/utils/settingsValidation/index.ts @@ -6,6 +6,8 @@ import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE } from '../constants'; import validImpressionsMode from './impressionsMode'; import { LogLevel } from '../../types'; import { ISettingsInternal, ISettingsValidationParams } from './types'; +import { logFactory } from '../../logger/sdkLogger'; +const log = logFactory('splitio'); const base = { // Define which kind of object you want to retrieve from SplitFactory @@ -78,7 +80,10 @@ const base = { splitFilters: undefined, // impressions collection mode impressionsMode: OPTIMIZED - } + }, + + // base logger + log }; function fromSecondsToMillis(n: number) { @@ -157,12 +162,12 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV } // validate the `splitFilters` settings and parse splits query - const splitFiltersValidation = validateSplitFilters(withDefaults.sync.splitFilters, withDefaults.mode); + const splitFiltersValidation = validateSplitFilters(withDefaults.log, withDefaults.sync.splitFilters, withDefaults.mode); withDefaults.sync.splitFilters = splitFiltersValidation.validFilters; // @ts-ignore withDefaults.sync.__splitFiltersValidation = splitFiltersValidation; // ensure a valid impressionsMode - withDefaults.sync.impressionsMode = validImpressionsMode(withDefaults.sync.impressionsMode); + withDefaults.sync.impressionsMode = validImpressionsMode(withDefaults.log, withDefaults.sync.impressionsMode); return withDefaults; } diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index e7a61bde..d0703bd7 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -1,5 +1,5 @@ -import { logFactory } from '../../../logger/sdkLogger'; -const log = logFactory('splitio-settings'); +// import { logFactory } from '../../../logger/sdkLogger'; +// const log = logFactory('splitio-settings'); /** * This function validates `settings.integrations` object @@ -21,7 +21,7 @@ export function validateIntegrations(settings: any, integrationValidator: (integ // Log a warning if at least one item is invalid const invalids = integrations.length - validIntegrations.length; - if (invalids) log.w(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); + if (invalids) settings.log.w(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); return validIntegrations; } diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index 5388acbd..a8b38085 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -1,9 +1,10 @@ import { STANDALONE_MODE } from '../constants'; import { validateSplits } from '../inputValidation/splits'; -import { logFactory } from '../../logger/sdkLogger'; import { ISplitFiltersValidation } from '../../dtos/types'; import { SplitIO } from '../../types'; -const log = logFactory(''); +import { ILogger } from '../../logger/types'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory(''); // Split filters metadata. // Ordered according to their precedency when forming the filter query string: `&names=&prefixes=` @@ -37,9 +38,9 @@ function validateFilterType(maybeFilterType: any): maybeFilterType is SplitIO.Sp * * @throws Error if the sanitized list exceeds the length indicated by `maxLength` */ -function validateSplitFilter(type: SplitIO.SplitFilterType, values: string[], maxLength: number) { +function validateSplitFilter(log: ILogger, type: SplitIO.SplitFilterType, values: string[], maxLength: number) { // validate and remove invalid and duplicated values - let result = validateSplits(values, 'Factory instantiation', `${type} filter`, `${type} filter value`); + let result = validateSplits(log, values, 'Factory instantiation', `${type} filter`, `${type} filter value`); if (result) { // check max length @@ -84,7 +85,7 @@ function queryStringBuilder(groupedFilters: Record { - if (res.groupedFilters[type].length > 0) res.groupedFilters[type] = validateSplitFilter(type, res.groupedFilters[type], maxLength); + if (res.groupedFilters[type].length > 0) res.groupedFilters[type] = validateSplitFilter(log, type, res.groupedFilters[type], maxLength); }); // build query string diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index 11021ea2..f1b74717 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -1,7 +1,7 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS'; import { ISettings } from '../../../types'; -import { logFactory } from '../../../logger/sdkLogger'; -const log = logFactory('splitio-settings'); +// import { logFactory } from '../../../logger/sdkLogger'; +// const log = logFactory('splitio-settings'); /** * This function validates `settings.storage` object @@ -17,7 +17,7 @@ export function validateStorageCS(settings: any): ISettings['storage'] { // @TODO validate its API (Splits cache, MySegments cache, etc) when supporting custom storages if (storage) { if (typeof storage === 'function') return storage; - log.w('The provided storage is invalid. Fallbacking into default MEMORY storage'); + settings.log.w('The provided storage is invalid. Fallbacking into default MEMORY storage'); } // return default InMemory storage if provided one is not valid From b50092a389513757309635646a05c75c3d2f6c58 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 1 Mar 2021 14:30:28 -0300 Subject: [PATCH 05/58] polishing to automatically migrate string messages to code messages --- src/integrations/ga/GaToSplit.ts | 4 ++-- src/integrations/ga/SplitToGa.ts | 6 ++---- src/logger/debugLogger.ts | 15 +++++++++++++++ src/logger/errorLogger.ts | 12 ++++++++++++ src/logger/index.ts | 4 ++-- src/logger/infoLogger.ts | 14 ++++++++++++++ src/logger/sdkLogger.ts | 9 ++++----- src/logger/warnLogger.ts | 13 +++++++++++++ src/services/splitHttpClient.ts | 2 +- src/storages/inLocalStorage/index.ts | 19 ++++++++++--------- src/sync/streaming/pushManager.ts | 2 +- src/sync/streaming/pushManagerCS.ts | 2 +- src/sync/streaming/pushManagerSS.ts | 2 +- src/utils/settingsValidation/index.ts | 9 +++++---- 14 files changed, 83 insertions(+), 30 deletions(-) create mode 100644 src/logger/debugLogger.ts create mode 100644 src/logger/errorLogger.ts create mode 100644 src/logger/infoLogger.ts create mode 100644 src/logger/warnLogger.ts diff --git a/src/integrations/ga/GaToSplit.ts b/src/integrations/ga/GaToSplit.ts index 9803d33e..92220efc 100644 --- a/src/integrations/ga/GaToSplit.ts +++ b/src/integrations/ga/GaToSplit.ts @@ -13,8 +13,8 @@ import { Identity, GoogleAnalyticsToSplitOptions } from './types'; import { ILogger } from '../../logger/types'; import { IIntegrationFactoryParams } from '../types'; // import { logFactory } from '../../logger/sdkLogger'; -const logName = 'splitio-ga-to-split', logNameMapper = logName + ':mapper'; -// const log = logFactory(logName); +// const log = logFactory('splitio-ga-to-split'); +const logNameMapper = 'splitio-ga-to-split:mapper'; /** * Provides a plugin to use with analytics.js, accounting for the possibility diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index 881d1952..23631828 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -8,8 +8,6 @@ import { ILogger } from '../../logger/types'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-split-to-ga'); -const noGaWarning = '`ga` command queue not found.'; - export default class SplitToGa implements IIntegration { // A falsy object represents the default tracker @@ -89,7 +87,7 @@ export default class SplitToGa implements IIntegration { } log.i('Started Split-to-GA integration'); - if (typeof SplitToGa.getGa() !== 'function') log.w(noGaWarning + ' No hits will be sent until it is available.'); + if (typeof SplitToGa.getGa() !== 'function') log.w('`ga` command queue not found. No hits will be sent until it is available.'); } queue(data: SplitIO.IntegrationData) { @@ -127,7 +125,7 @@ export default class SplitToGa implements IIntegration { ga(sendCommand, fieldsObject); }); } else { - this.log.w(noGaWarning + ' No hit was sent.'); + this.log.w('`ga` command queue not found. No hit was sent.'); } } diff --git a/src/logger/debugLogger.ts b/src/logger/debugLogger.ts new file mode 100644 index 00000000..b9ae4993 --- /dev/null +++ b/src/logger/debugLogger.ts @@ -0,0 +1,15 @@ +import { Logger } from '.'; +import { codesDebug } from './codesDebug'; +import { codesError } from './codesError'; +import { codesInfo } from './codesInfo'; +import { codesWarn } from './codesWarn'; + +const codes = { + ERROR: codesError, + WARN: codesWarn, + INFO: codesInfo, + DEBUG: codesDebug, + NONE: [], +}; + +export const debugLogger = new Logger(undefined, undefined, codes); diff --git a/src/logger/errorLogger.ts b/src/logger/errorLogger.ts new file mode 100644 index 00000000..a9d1ada7 --- /dev/null +++ b/src/logger/errorLogger.ts @@ -0,0 +1,12 @@ +import { Logger } from '.'; +import { codesError } from './codesError'; + +const codes = { + ERROR: codesError, + WARN: [], + INFO: [], + DEBUG: [], + NONE: [], +}; + +export const errorLogger = new Logger(undefined, undefined, codes); diff --git a/src/logger/index.ts b/src/logger/index.ts index 27cc1d87..5467d9d8 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -36,11 +36,11 @@ const defaultOptions = { export class Logger implements ILogger { - private category: string; + private category?: string; private options: ILoggerOptions; private codes: ICodes; - constructor(category: string, options: ILoggerOptions, codes: ICodes) { + constructor(category: string | undefined, options: ILoggerOptions | undefined, codes: ICodes) { this.category = category; this.options = objectAssign({}, defaultOptions, options); this.codes = codes; diff --git a/src/logger/infoLogger.ts b/src/logger/infoLogger.ts new file mode 100644 index 00000000..c4d06d9b --- /dev/null +++ b/src/logger/infoLogger.ts @@ -0,0 +1,14 @@ +import { Logger } from '.'; +import { codesError } from './codesError'; +import { codesInfo } from './codesInfo'; +import { codesWarn } from './codesWarn'; + +const codes = { + ERROR: codesError, + WARN: codesWarn, + INFO: codesInfo, + DEBUG: [], + NONE: [], +}; + +export const infoLogger = new Logger(undefined, undefined, codes); diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 9fd0ae6f..90aa1e33 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -1,13 +1,12 @@ /** * This file defines the logger interface and default options for the SDKs, not necessarily for the Logger as it's own. */ -import { ILoggerOptions } from './types'; +import { ICodes, ILoggerOptions } from './types'; import { Logger, LogLevels, setLogLevel, isLogLevelString } from '.'; import { isLocalStorageAvailable } from '../utils/env/isLocalStorageAvailable'; import { isNode } from '../utils/env/isNode'; import { merge } from '../utils/lang'; import { ILoggerAPI } from '../types'; -import { codes } from './codes'; // @TODO when integrating with other packages, find the best way to update LoggerOption defaults per package (node, evaluator, etc.) const defaultOptions: ILoggerOptions = { @@ -31,9 +30,9 @@ const initialState = String( ); // we expose the logger instance creator -export const logFactory = (namespace: string, options = {}) => new Logger(namespace, merge(options, defaultOptions), codes); +export const logFactory = (namespace: string, options = {}, codes: ICodes) => new Logger(namespace, merge(options, defaultOptions), codes); -const ownLog = logFactory('splitio-utils:logger'); +// const log = logFactory('splitio-utils:logger'); /** * The public Logger utility API exposed via SplitFactory. @@ -53,7 +52,7 @@ export const API: ILoggerAPI = { if (isLogLevelString(logLevel)) { setLogLevel(logLevel); } else { - ownLog.e('Invalid Log Level - No changes to the logs will be applied.'); + // log.e('Invalid Log Level - No changes to the logs will be applied.'); } }, /** diff --git a/src/logger/warnLogger.ts b/src/logger/warnLogger.ts new file mode 100644 index 00000000..3f28a03a --- /dev/null +++ b/src/logger/warnLogger.ts @@ -0,0 +1,13 @@ +import { Logger } from '.'; +import { codesError } from './codesError'; +import { codesWarn } from './codesWarn'; + +const codes = { + ERROR: codesError, + WARN: codesWarn, + INFO: [], + DEBUG: [], + NONE: [], +}; + +export const warnLogger = new Logger(undefined, undefined, codes); diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index b176c873..77eadaf3 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -22,7 +22,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I const fetch = getFetch && getFetch(); // if fetch is not available, log Error - if (!fetch) log.e(messageNoFetch + ' The SDK will not get ready.'); + if (!fetch) log.e(`${messageNoFetch} The SDK will not get ready.`); const headers: Record = { 'Accept': 'application/json', diff --git a/src/storages/inLocalStorage/index.ts b/src/storages/inLocalStorage/index.ts index fa2f3fbb..cb5960de 100644 --- a/src/storages/inLocalStorage/index.ts +++ b/src/storages/inLocalStorage/index.ts @@ -9,8 +9,9 @@ import MySegmentsCacheInLocal from './MySegmentsCacheInLocal'; import MySegmentsCacheInMemory from '../inMemory/MySegmentsCacheInMemory'; import SplitsCacheInMemory from '../inMemory/SplitsCacheInMemory'; import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-storage:localstorage'); +import { InMemoryStorageCSFactory } from '../../storages/inMemory/InMemoryStorageCS'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-storage:localstorage'); export interface InLocalStorageOptions { prefix?: string @@ -21,15 +22,15 @@ export interface InLocalStorageOptions { */ export function InLocalStorage(options: InLocalStorageOptions = {}) { - // Fallback to InMemoryStorage if LocalStorage API is not available - if (!isLocalStorageAvailable()) { - log.w('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); - return; - } + return function InLocalStorageCSFactory(params: IStorageFactoryParams): IStorageSyncCS { - const prefix = options.prefix ? options.prefix + '.SPLITIO' : 'SPLITIO'; + // Fallback to InMemoryStorage if LocalStorage API is not available + if (!isLocalStorageAvailable()) { + params.log.w('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); + return InMemoryStorageCSFactory(params); + } - return function InLocalStorageCSFactory(params: IStorageFactoryParams): IStorageSyncCS { + const prefix = options.prefix ? options.prefix + '.SPLITIO' : 'SPLITIO'; const log = params.log; const keys = new KeyBuilderCS(prefix, params.matchingKey as string); diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index e6ddbd74..33908e4f 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -41,7 +41,7 @@ export default function pushManagerFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.w(e + 'Falling back to polling mode.'); + log.w(`${e}Falling back to polling mode.`); return; } const authenticate = authenticateFactory(fetchAuth); diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index 0fa34051..e6a261e0 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -39,7 +39,7 @@ export default function pushManagerCSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.w(e + 'Falling back to polling mode.'); + log.w(`${e}Falling back to polling mode.`); return; } const authenticate = authenticateFactory(fetchAuth); diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index 23993a7a..bd5c018e 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -35,7 +35,7 @@ export default function pushManagerSSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.w(e + 'Falling back to polling mode.'); + log.w(`${e}Falling back to polling mode.`); return; } const authenticate = authenticateFactory(fetchAuth); diff --git a/src/utils/settingsValidation/index.ts b/src/utils/settingsValidation/index.ts index 655787b9..2094aaf7 100644 --- a/src/utils/settingsValidation/index.ts +++ b/src/utils/settingsValidation/index.ts @@ -6,8 +6,9 @@ import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE } from '../constants'; import validImpressionsMode from './impressionsMode'; import { LogLevel } from '../../types'; import { ISettingsInternal, ISettingsValidationParams } from './types'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio'); +import { noopLogger } from '../../logger/noopLogger'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio'); const base = { // Define which kind of object you want to retrieve from SplitFactory @@ -82,8 +83,8 @@ const base = { impressionsMode: OPTIMIZED }, - // base logger - log + // the default logger ignores all logs + log: noopLogger }; function fromSecondsToMillis(n: number) { From eacff0d1041e7d522dd76b830d7fb68fb4531728 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 3 Mar 2021 15:06:36 -0300 Subject: [PATCH 06/58] updated version --- jest.config.js | 2 +- package-lock.json | 2 +- package.json | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/jest.config.js b/jest.config.js index ed62d821..439ab3b6 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,7 +2,7 @@ module.exports = { preset: 'ts-jest', // Test files are .js and .ts files inside of __tests__ folders and with a suffix of .test or .spec - testMatch: ['**/__tests__/**/?(*.)+(spec|test).[jt]s'], + testMatch: ['/src/**/__tests__/**/?(*.)+(spec|test).[jt]s'], // Included files for test coverage (npm run test:coverage) collectCoverageFrom: [ diff --git a/package-lock.json b/package-lock.json index 67225cc9..a4d7edff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "0.0.1-beta1", + "version": "0.0.1-beta.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0bac85bd..d0a9df2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "0.0.1-beta1", + "version": "0.0.1-beta.2", "description": "Split Javascript SDK common components", "main": "cjs/index.js", "module": "esm/index.js", @@ -24,7 +24,8 @@ "build:cjs": "rimraf cjs && tsc -m CommonJS --outDir cjs --importHelpers", "test": "jest", "test:coverage": "jest --coverage", - "publish:rc": "npm run check && npm run test && npm run build && npm publish --tag rc" + "publish:rc": "npm run check && npm run test && npm run build && npm publish --tag rc", + "publish:stable": "npm run check && npm run test && npm run build && npm publish" }, "repository": { "type": "git", From 6ad222255443eb979a4abc64f3b31be30e0e142a Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 3 Mar 2021 15:39:39 -0300 Subject: [PATCH 07/58] rollback shorten methods --- src/evaluator/combiners/and.ts | 2 +- src/evaluator/combiners/ifelseif.ts | 6 +++--- src/evaluator/matchers/all.ts | 2 +- src/evaluator/matchers/between.ts | 2 +- src/evaluator/matchers/boolean.ts | 2 +- src/evaluator/matchers/cont_all.ts | 2 +- src/evaluator/matchers/cont_any.ts | 2 +- src/evaluator/matchers/cont_str.ts | 2 +- src/evaluator/matchers/dependency.ts | 4 ++-- src/evaluator/matchers/eq.ts | 2 +- src/evaluator/matchers/eq_set.ts | 2 +- src/evaluator/matchers/ew.ts | 2 +- src/evaluator/matchers/gte.ts | 2 +- src/evaluator/matchers/lte.ts | 2 +- src/evaluator/matchers/part_of.ts | 2 +- src/evaluator/matchers/segment.ts | 4 ++-- src/evaluator/matchers/string.ts | 4 ++-- src/evaluator/matchers/sw.ts | 2 +- src/evaluator/matchers/whitelist.ts | 2 +- src/evaluator/value/index.ts | 6 +++--- src/evaluator/value/sanitize.ts | 2 +- src/integrations/ga/GaToSplit.ts | 14 +++++++------- src/integrations/ga/SplitToGa.ts | 10 +++++----- src/listeners/browser.ts | 4 ++-- src/listeners/node.ts | 8 ++++---- src/logger/index.ts | 8 ++++---- src/logger/noopLogger.ts | 8 ++++---- src/logger/sdkLogger.ts | 2 +- src/logger/types.ts | 8 ++++---- src/readiness/sdkReadinessManager.ts | 8 ++++---- src/sdkClient/client.ts | 4 ++-- src/sdkClient/sdkClientMethod.ts | 2 +- src/sdkClient/sdkClientMethodCS.ts | 6 +++--- src/sdkClient/sdkClientMethodCSWithTT.ts | 6 +++--- src/sdkFactory/index.ts | 6 +++--- src/services/splitHttpClient.ts | 4 ++-- .../inLocalStorage/MySegmentsCacheInLocal.ts | 6 +++--- .../inLocalStorage/SplitsCacheInLocal.ts | 18 +++++++++--------- src/storages/inLocalStorage/index.ts | 2 +- src/storages/inRedis/EventsCacheInRedis.ts | 2 +- src/storages/inRedis/RedisAdapter.ts | 18 +++++++++--------- src/storages/inRedis/SplitsCacheInRedis.ts | 10 +++++----- .../splitsParser/splitsParserFromFile.ts | 12 ++++++------ .../offline/syncTasks/fromObjectSyncTask.ts | 6 +++--- src/sync/polling/pollingManagerCS.ts | 6 +++--- src/sync/polling/pollingManagerSS.ts | 8 ++++---- .../polling/syncTasks/mySegmentsSyncTask.ts | 2 +- src/sync/polling/syncTasks/segmentsSyncTask.ts | 8 ++++---- src/sync/polling/syncTasks/splitsSyncTask.ts | 12 ++++++------ src/sync/streaming/SSEHandler/index.ts | 6 +++--- src/sync/streaming/pushManager.ts | 16 ++++++++-------- src/sync/streaming/pushManagerCS.ts | 16 ++++++++-------- src/sync/streaming/pushManagerSS.ts | 16 ++++++++-------- src/sync/submitters/eventsSyncTask.ts | 2 +- src/sync/submitters/submitterSyncTask.ts | 8 ++++---- src/sync/syncManagerOnline.ts | 6 +++--- src/sync/syncTask.ts | 6 +++--- src/trackers/eventTracker.ts | 4 ++-- src/trackers/impressionsTracker.ts | 6 +++--- src/utils/inputValidation/apiKey.ts | 10 +++++----- src/utils/inputValidation/attributes.ts | 2 +- src/utils/inputValidation/event.ts | 8 ++++---- src/utils/inputValidation/eventProperties.ts | 8 ++++---- src/utils/inputValidation/eventValue.ts | 2 +- src/utils/inputValidation/isOperational.ts | 4 ++-- src/utils/inputValidation/key.ts | 12 ++++++------ src/utils/inputValidation/preloadedData.ts | 12 ++++++------ src/utils/inputValidation/split.ts | 8 ++++---- src/utils/inputValidation/splitExistance.ts | 2 +- src/utils/inputValidation/splits.ts | 2 +- src/utils/inputValidation/trafficType.ts | 8 ++++---- .../inputValidation/trafficTypeExistance.ts | 2 +- .../settingsValidation/impressionsMode.ts | 2 +- .../settingsValidation/integrations/common.ts | 2 +- src/utils/settingsValidation/splitFilters.ts | 8 ++++---- .../settingsValidation/storage/storageCS.ts | 2 +- src/utils/timeTracker/index.ts | 2 +- 77 files changed, 223 insertions(+), 223 deletions(-) diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index b6fb61fb..5fa02e11 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -12,7 +12,7 @@ export default function andCombinerContext(matchers: IMatcher[], log: ILogger) { // Array.prototype.every is supported by target environments const hasMatchedAll = results.every(value => value); - log.d(`[andCombiner] evaluates to ${hasMatchedAll}`); + log.debug(`[andCombiner] evaluates to ${hasMatchedAll}`); return hasMatchedAll; } diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index c9e2be5e..2cdc7874 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -11,7 +11,7 @@ import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; export default function ifElseIfCombinerContext(predicates: IEvaluator[], log: ILogger): IEvaluator { function unexpectedInputHandler() { - log.e('Invalid Split provided, no valid conditions found'); + log.error('Invalid Split provided, no valid conditions found'); return { treatment: CONTROL, @@ -26,13 +26,13 @@ export default function ifElseIfCombinerContext(predicates: IEvaluator[], log: I const evaluation = predicateResults[i]; if (evaluation !== undefined) { - log.d(`Treatment found: ${evaluation.treatment}`); + log.debug(`Treatment found: ${evaluation.treatment}`); return evaluation; } } - log.d('All predicates evaluated, no treatment found.'); + log.debug('All predicates evaluated, no treatment found.'); return undefined; } diff --git a/src/evaluator/matchers/all.ts b/src/evaluator/matchers/all.ts index a186f40d..6e40c319 100644 --- a/src/evaluator/matchers/all.ts +++ b/src/evaluator/matchers/all.ts @@ -4,7 +4,7 @@ import { ILogger } from '../../logger/types'; export default function allMatcherContext(log: ILogger) { return function allMatcher(runtimeAttr: string): boolean { - log.d('[allMatcher] is always true'); + log.debug('[allMatcher] is always true'); return runtimeAttr != null; }; diff --git a/src/evaluator/matchers/between.ts b/src/evaluator/matchers/between.ts index bdb2e899..db2cbb3a 100644 --- a/src/evaluator/matchers/between.ts +++ b/src/evaluator/matchers/between.ts @@ -8,7 +8,7 @@ export default function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatc let isBetween = runtimeAttr >= ruleVO.start && runtimeAttr <= ruleVO.end; - log.d(`[betweenMatcher] is ${runtimeAttr} between ${ruleVO.start} and ${ruleVO.end}? ${isBetween}`); + log.debug(`[betweenMatcher] is ${runtimeAttr} between ${ruleVO.start} and ${ruleVO.end}? ${isBetween}`); return isBetween; }; diff --git a/src/evaluator/matchers/boolean.ts b/src/evaluator/matchers/boolean.ts index daba4766..d47befd5 100644 --- a/src/evaluator/matchers/boolean.ts +++ b/src/evaluator/matchers/boolean.ts @@ -6,7 +6,7 @@ export default function booleanMatcherContext(log: ILogger, ruleAttr: boolean) / return function booleanMatcher(runtimeAttr: boolean): boolean { let booleanMatches = ruleAttr === runtimeAttr; - log.d(`[booleanMatcher] ${ruleAttr} === ${runtimeAttr}`); + log.debug(`[booleanMatcher] ${ruleAttr} === ${runtimeAttr}`); return booleanMatches; }; diff --git a/src/evaluator/matchers/cont_all.ts b/src/evaluator/matchers/cont_all.ts index ae5842c1..48fcceb8 100644 --- a/src/evaluator/matchers/cont_all.ts +++ b/src/evaluator/matchers/cont_all.ts @@ -16,7 +16,7 @@ export default function containsAllMatcherContext(log: ILogger, ruleAttr: string } } - log.d(`[containsAllMatcher] ${runtimeAttr} contains all elements of ${ruleAttr}? ${containsAll}`); + log.debug(`[containsAllMatcher] ${runtimeAttr} contains all elements of ${ruleAttr}? ${containsAll}`); return containsAll; }; diff --git a/src/evaluator/matchers/cont_any.ts b/src/evaluator/matchers/cont_any.ts index f1b8ae90..1a606dbe 100644 --- a/src/evaluator/matchers/cont_any.ts +++ b/src/evaluator/matchers/cont_any.ts @@ -11,7 +11,7 @@ export default function containsAnyMatcherContext(log: ILogger, ruleAttr: string if (findIndex(runtimeAttr, e => e === ruleAttr[i]) >= 0) containsAny = true; } - log.d(`[containsAnyMatcher] ${runtimeAttr} contains at least an element of ${ruleAttr}? ${containsAny}`); + log.debug(`[containsAnyMatcher] ${runtimeAttr} contains at least an element of ${ruleAttr}? ${containsAny}`); return containsAny; }; diff --git a/src/evaluator/matchers/cont_str.ts b/src/evaluator/matchers/cont_str.ts index 6f9d61c7..5aad4dd2 100644 --- a/src/evaluator/matchers/cont_str.ts +++ b/src/evaluator/matchers/cont_str.ts @@ -7,7 +7,7 @@ export default function containsStringMatcherContext(log: ILogger, ruleAttr: str return function containsStringMatcher(runtimeAttr: string): boolean { let contains = ruleAttr.some(e => isString(runtimeAttr) && runtimeAttr.indexOf(e) > -1); - log.d(`[containsStringMatcher] ${runtimeAttr} contains ${ruleAttr}? ${contains}`); + log.debug(`[containsStringMatcher] ${runtimeAttr} contains ${ruleAttr}? ${contains}`); return contains; }; diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index ba95c965..e0778649 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -15,13 +15,13 @@ export default function dependencyMatcherContext(log: ILogger, { split, treatmen matches = acceptableTreatments.indexOf(evaluation.treatment as string) !== -1; } - log.d(`[dependencyMatcher] Parent split "${parentName}" evaluated to "${evaluation.treatment}" with label "${evaluation.label}". ${parentName} evaluated treatment is part of [${acceptableTreatments}] ? ${matches}.`); + log.debug(`[dependencyMatcher] Parent split "${parentName}" evaluated to "${evaluation.treatment}" with label "${evaluation.label}". ${parentName} evaluated treatment is part of [${acceptableTreatments}] ? ${matches}.`); return matches; } return function dependencyMatcher({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator): MaybeThenable { - log.d(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? `\n attributes: ${JSON.stringify(attributes)}` : ''}`); + log.debug(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? `\n attributes: ${JSON.stringify(attributes)}` : ''}`); const evaluation = splitEvaluator(key, split, attributes, storage, log); if (thenable(evaluation)) { diff --git a/src/evaluator/matchers/eq.ts b/src/evaluator/matchers/eq.ts index 71e3b924..891c42f6 100644 --- a/src/evaluator/matchers/eq.ts +++ b/src/evaluator/matchers/eq.ts @@ -6,7 +6,7 @@ export default function equalToMatcherContext(log: ILogger, ruleAttr: number) /* return function equalToMatcher(runtimeAttr: number): boolean { let isEqual = runtimeAttr === ruleAttr; - log.d(`[equalToMatcher] is ${runtimeAttr} equal to ${ruleAttr}? ${isEqual}`); + log.debug(`[equalToMatcher] is ${runtimeAttr} equal to ${ruleAttr}? ${isEqual}`); return isEqual; }; diff --git a/src/evaluator/matchers/eq_set.ts b/src/evaluator/matchers/eq_set.ts index a53e6f16..88b4bb63 100644 --- a/src/evaluator/matchers/eq_set.ts +++ b/src/evaluator/matchers/eq_set.ts @@ -13,7 +13,7 @@ export default function equalToSetMatcherContext(log: ILogger, ruleAttr: string[ if (findIndex(ruleAttr, e => e === runtimeAttr[i]) < 0) isEqual = false; } - log.d(`[equalToSetMatcher] is ${runtimeAttr} equal to set ${ruleAttr}? ${isEqual}`); + log.debug(`[equalToSetMatcher] is ${runtimeAttr} equal to set ${ruleAttr}? ${isEqual}`); return isEqual; }; diff --git a/src/evaluator/matchers/ew.ts b/src/evaluator/matchers/ew.ts index d7cf5178..7b8df448 100644 --- a/src/evaluator/matchers/ew.ts +++ b/src/evaluator/matchers/ew.ts @@ -7,7 +7,7 @@ export default function endsWithMatcherContext(log: ILogger, ruleAttr: string[]) return function endsWithMatcher(runtimeAttr: string): boolean { let endsWith = ruleAttr.some(e => strEndsWith(runtimeAttr, e)); - log.d(`[endsWithMatcher] ${runtimeAttr} ends with ${ruleAttr}? ${endsWith}`); + log.debug(`[endsWithMatcher] ${runtimeAttr} ends with ${ruleAttr}? ${endsWith}`); return endsWith; }; diff --git a/src/evaluator/matchers/gte.ts b/src/evaluator/matchers/gte.ts index fb89f48c..0d147c95 100644 --- a/src/evaluator/matchers/gte.ts +++ b/src/evaluator/matchers/gte.ts @@ -6,7 +6,7 @@ export default function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: n return function greaterThanEqualMatcher(runtimeAttr: number): boolean { let isGreaterEqualThan = runtimeAttr >= ruleAttr; - log.d(`[greaterThanEqualMatcher] is ${runtimeAttr} greater than ${ruleAttr}? ${isGreaterEqualThan}`); + log.debug(`[greaterThanEqualMatcher] is ${runtimeAttr} greater than ${ruleAttr}? ${isGreaterEqualThan}`); return isGreaterEqualThan; }; diff --git a/src/evaluator/matchers/lte.ts b/src/evaluator/matchers/lte.ts index 9b9720fd..95808a74 100644 --- a/src/evaluator/matchers/lte.ts +++ b/src/evaluator/matchers/lte.ts @@ -6,7 +6,7 @@ export default function lessThanEqualMatcherContext(log: ILogger, ruleAttr: numb return function lessThanEqualMatcher(runtimeAttr: number): boolean { let isLessEqualThan = runtimeAttr <= ruleAttr; - log.d(`[lessThanEqualMatcher] is ${runtimeAttr} less than ${ruleAttr}? ${isLessEqualThan}`); + log.debug(`[lessThanEqualMatcher] is ${runtimeAttr} less than ${ruleAttr}? ${isLessEqualThan}`); return isLessEqualThan; }; diff --git a/src/evaluator/matchers/part_of.ts b/src/evaluator/matchers/part_of.ts index 7288f611..c0218818 100644 --- a/src/evaluator/matchers/part_of.ts +++ b/src/evaluator/matchers/part_of.ts @@ -13,7 +13,7 @@ export default function partOfMatcherContext(log: ILogger, ruleAttr: string[]) / if (findIndex(ruleAttr, e => e === runtimeAttr[i]) < 0) isPartOf = false; } - log.d(`[partOfMatcher] ${runtimeAttr} is part of ${ruleAttr}? ${isPartOf}`); + log.debug(`[partOfMatcher] ${runtimeAttr} is part of ${ruleAttr}? ${isPartOf}`); return isPartOf; }; diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index 0c574745..7834f57a 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -12,12 +12,12 @@ export default function matcherSegmentContext(log: ILogger, segmentName: string, if (thenable(isInSegment)) { isInSegment.then(result => { - log.d(`[asyncSegmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); + log.debug(`[asyncSegmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); return result; }); } else { - log.d(`[segmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); + log.debug(`[segmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); } return isInSegment; diff --git a/src/evaluator/matchers/string.ts b/src/evaluator/matchers/string.ts index f955c234..8d437f79 100644 --- a/src/evaluator/matchers/string.ts +++ b/src/evaluator/matchers/string.ts @@ -9,14 +9,14 @@ export default function stringMatcherContext(log: ILogger, ruleAttr: string) /*: try { re = new RegExp(ruleAttr); } catch (e) { - log.d(`[stringMatcher] ${ruleAttr} is an invalid regex`); + log.debug(`[stringMatcher] ${ruleAttr} is an invalid regex`); return false; } let regexMatches = re.test(runtimeAttr); - log.d(`[stringMatcher] does ${runtimeAttr} matches with ${ruleAttr}? ${regexMatches ? 'yes' : 'no'}`); + log.debug(`[stringMatcher] does ${runtimeAttr} matches with ${ruleAttr}? ${regexMatches ? 'yes' : 'no'}`); return regexMatches; }; diff --git a/src/evaluator/matchers/sw.ts b/src/evaluator/matchers/sw.ts index d0d8d3d4..a5422b0a 100644 --- a/src/evaluator/matchers/sw.ts +++ b/src/evaluator/matchers/sw.ts @@ -7,7 +7,7 @@ export default function startsWithMatcherContext(log: ILogger, ruleAttr: string[ return function startsWithMatcher(runtimeAttr: string): boolean { let matches = ruleAttr.some(e => startsWith(runtimeAttr, e)); - log.d(`[startsWithMatcher] ${runtimeAttr} starts with ${ruleAttr}? ${matches}`); + log.debug(`[startsWithMatcher] ${runtimeAttr} starts with ${ruleAttr}? ${matches}`); return matches; }; diff --git a/src/evaluator/matchers/whitelist.ts b/src/evaluator/matchers/whitelist.ts index 0707580f..735a6cb5 100644 --- a/src/evaluator/matchers/whitelist.ts +++ b/src/evaluator/matchers/whitelist.ts @@ -7,7 +7,7 @@ export default function whitelistMatcherContext(log: ILogger, ruleAttr: ISet ${isInWhitelist}`); + log.debug(`[whitelistMatcher] evaluated ${runtimeAttr} in [${setToArray(ruleAttr).join(',')}] => ${isInWhitelist}`); return isInWhitelist; }; diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index fd50b791..91d3a18a 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -10,9 +10,9 @@ function parseValue(key: string, attributeName: string | null, attributes: Split if (attributeName) { if (attributes) { value = attributes[attributeName]; - log.d(`Extracted attribute [${attributeName}], [${value}] will be used for matching.`); + log.debug(`Extracted attribute [${attributeName}], [${value}] will be used for matching.`); } else { - log.w(`Defined attribute [${attributeName}], no attributes received.`); + log.warn(`Defined attribute [${attributeName}], no attributes received.`); } } else { value = key; @@ -32,7 +32,7 @@ export default function value(key: string, matcherDto: IMatcherDto, attributes: if (sanitizedValue !== undefined) { return sanitizedValue; } else { - log.w(`Value ${valueToMatch} ${attributeName ? `for attribute ${attributeName} ` : + ''}doesn't match with expected type.`); + log.warn(`Value ${valueToMatch} ${attributeName ? `for attribute ${attributeName} ` : + ''}doesn't match with expected type.`); return; } } diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index b47f5ef4..ff1a98d5 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -100,7 +100,7 @@ export default function sanitize(matcherTypeID: number, value: string | number | sanitizedValue = processor(sanitizedValue, attributes); } - log.d(`Attempted to sanitize [${value}] which should be of type [${dataType}]. \n Sanitized and processed value => [${sanitizedValue instanceof Object ? JSON.stringify(sanitizedValue) : sanitizedValue}]`); + log.debug(`Attempted to sanitize [${value}] which should be of type [${dataType}]. \n Sanitized and processed value => [${sanitizedValue instanceof Object ? JSON.stringify(sanitizedValue) : sanitizedValue}]`); return sanitizedValue; } diff --git a/src/integrations/ga/GaToSplit.ts b/src/integrations/ga/GaToSplit.ts index 9803d33e..0346044d 100644 --- a/src/integrations/ga/GaToSplit.ts +++ b/src/integrations/ga/GaToSplit.ts @@ -168,7 +168,7 @@ export function fixEventTypeId(eventTypeId: any, log: ILogger) { .replace(INVALID_PREFIX_REGEX, '') .replace(INVALID_SUBSTRING_REGEX, '_'); const truncated = fixed.slice(0, 80); - if (truncated.length < fixed.length) log.w('EventTypeId was truncated because it cannot be more than 80 characters long.'); + if (truncated.length < fixed.length) log.warn('EventTypeId was truncated because it cannot be more than 80 characters long.'); return truncated; } @@ -209,19 +209,19 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par const validIdentities = validateIdentities(opts.identities); if (validIdentities.length === 0) { - log.w('No valid identities were provided. Please check that you are passing a valid list of identities or providing a traffic type at the SDK configuration.'); + log.warn('No valid identities were provided. Please check that you are passing a valid list of identities or providing a traffic type at the SDK configuration.'); return; } const invalids = validIdentities.length - opts.identities.length; if (invalids) { - log.w(`${invalids} identities were discarded because they are invalid or duplicated. Identities must be an array of objects with key and trafficType.`); + log.warn(`${invalids} identities were discarded because they are invalid or duplicated. Identities must be an array of objects with key and trafficType.`); } opts.identities = validIdentities; // Validate prefix if (!isString(opts.prefix)) { - log.w('The provided `prefix` was ignored since it is invalid. Please check that you are passing a string object as `prefix`.'); + log.warn('The provided `prefix` was ignored since it is invalid. Please check that you are passing a string object as `prefix`.'); opts.prefix = undefined; } @@ -238,7 +238,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par try { if (opts.filter && !opts.filter(model)) return; } catch (err) { - log.w(`GaToSplit custom filter threw: ${err}`); + log.warn(`GaToSplit custom filter threw: ${err}`); return; } @@ -248,7 +248,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par try { eventData = opts.mapper(model, eventData as SplitIO.EventData); } catch (err) { - log.w(`GaToSplit custom mapper threw: ${err}`); + log.warn(`GaToSplit custom mapper threw: ${err}`); return; } if (!eventData) @@ -277,7 +277,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par } }); - log.i('Started GA-to-Split integration'); + log.info('Started GA-to-Split integration'); } } diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index 881d1952..7e01dfdf 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -62,7 +62,7 @@ export default class SplitToGa implements IIntegration { static validateFieldsObject(fieldsObject: any, log: ILogger): fieldsObject is UniversalAnalytics.FieldsObject { if (fieldsObject && fieldsObject.hitType) return true; - log.w('your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.'); + log.warn('your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.'); return false; } @@ -88,8 +88,8 @@ export default class SplitToGa implements IIntegration { this.events = options.events; } - log.i('Started Split-to-GA integration'); - if (typeof SplitToGa.getGa() !== 'function') log.w(noGaWarning + ' No hits will be sent until it is available.'); + log.info('Started Split-to-GA integration'); + if (typeof SplitToGa.getGa() !== 'function') log.warn(noGaWarning + ' No hits will be sent until it is available.'); } queue(data: SplitIO.IntegrationData) { @@ -114,7 +114,7 @@ export default class SplitToGa implements IIntegration { if (!fieldsObject || !SplitToGa.validateFieldsObject(fieldsObject, this.log)) return; } } catch (err) { - this.log.w(`SplitToGa queue method threw: ${err}. No hit was sent.`); + this.log.warn(`SplitToGa queue method threw: ${err}. No hit was sent.`); return; } @@ -127,7 +127,7 @@ export default class SplitToGa implements IIntegration { ga(sendCommand, fieldsObject); }); } else { - this.log.w(noGaWarning + ' No hit was sent.'); + this.log.warn(noGaWarning + ' No hit was sent.'); } } diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index c6052f0b..cf65d460 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -41,7 +41,7 @@ export default class BrowserSignalListener implements ISignalListener { */ start() { if (typeof window !== 'undefined' && window.addEventListener) { - this.settings.log.d('Registering flush handler when unload page event is triggered.'); + this.settings.log.debug('Registering flush handler when unload page event is triggered.'); window.addEventListener(UNLOAD_DOM_EVENT, this.flushData); } } @@ -53,7 +53,7 @@ export default class BrowserSignalListener implements ISignalListener { */ stop() { if (typeof window !== 'undefined' && window.removeEventListener) { - this.settings.log.d('Deregistering flush handler when unload page event is triggered.'); + this.settings.log.debug('Deregistering flush handler when unload page event is triggered.'); window.removeEventListener(UNLOAD_DOM_EVENT, this.flushData); } } diff --git a/src/listeners/node.ts b/src/listeners/node.ts index 7c1ff408..0fb72f4c 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -23,13 +23,13 @@ export default class NodeSignalListener implements ISignalListener { } start() { - this.settings.log.d('Registering cleanup handlers.'); + this.settings.log.debug('Registering cleanup handlers.'); // eslint-disable-next-line no-undef process.on('SIGTERM', this._sigtermHandler); } stop() { - this.settings.log.d('Deregistering cleanup handlers.'); + this.settings.log.debug('Deregistering cleanup handlers.'); // eslint-disable-next-line no-undef process.removeListener('SIGTERM', this._sigtermHandler); } @@ -47,14 +47,14 @@ export default class NodeSignalListener implements ISignalListener { process.kill(process.pid, 'SIGTERM'); }; - this.settings.log.d('Split SDK graceful shutdown after SIGTERM.'); + this.settings.log.debug('Split SDK graceful shutdown after SIGTERM.'); let handlerResult = null; try { handlerResult = this.handler(); } catch (err) { - this.settings.log.e(`Error with Split graceful shutdown: ${err}`); + this.settings.log.error(`Error with Split graceful shutdown: ${err}`); } if (thenable(handlerResult)) { diff --git a/src/logger/index.ts b/src/logger/index.ts index 3078422f..d8fe71fd 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -36,22 +36,22 @@ export class Logger implements ILogger { this.options = objectAssign({}, defaultOptions, options); } - d(msg: string) { + debug(msg: string) { if (this._shouldLog(LogLevels.DEBUG)) this._log(LogLevels.DEBUG, msg); } - i(msg: string) { + info(msg: string) { if (this._shouldLog(LogLevels.INFO)) this._log(LogLevels.INFO, msg); } - w(msg: string) { + warn(msg: string) { if (this._shouldLog(LogLevels.WARN)) this._log(LogLevels.WARN, msg); } - e(msg: string) { + error(msg: string) { if (this.options.displayAllErrors || this._shouldLog(LogLevels.ERROR)) this._log(LogLevels.ERROR, msg); } diff --git a/src/logger/noopLogger.ts b/src/logger/noopLogger.ts index 36d77895..df89763d 100644 --- a/src/logger/noopLogger.ts +++ b/src/logger/noopLogger.ts @@ -1,8 +1,8 @@ import { ILogger } from './types'; export const noopLogger: ILogger = { - d() {}, - i() {}, - w() {}, - e() {}, + debug() {}, + info() {}, + warn() {}, + error() {}, }; diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 0e0ab37e..a7dbe9a8 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -52,7 +52,7 @@ export const API: ILoggerAPI = { if (isLogLevelString(logLevel)) { setLogLevel(logLevel); } else { - ownLog.e('Invalid Log Level - No changes to the logs will be applied.'); + ownLog.error('Invalid Log Level - No changes to the logs will be applied.'); } }, /** diff --git a/src/logger/types.ts b/src/logger/types.ts index 0ffd499b..62ac8628 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -4,11 +4,11 @@ export interface ILoggerOptions { } export interface ILogger { - d(msg: string): void + debug(msg: string): void - i(msg: string): void + info(msg: string): void - w(msg: string): void + warn(msg: string): void - e(msg: string): void + error(msg: string): void } diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index 01267f5c..87f165d5 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -41,7 +41,7 @@ export default function sdkReadinessManagerFactory( readinessManager.gate.on(NEW_LISTENER_EVENT, (event: any) => { if (event === SDK_READY || event === SDK_READY_TIMED_OUT) { if (readinessManager.isReady()) { - log.e(`A listener was added for ${event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT'} on the SDK, which has already fired and won't be emitted again. The callback won't be executed.`); + log.error(`A listener was added for ${event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT'} on the SDK, which has already fired and won't be emitted again. The callback won't be executed.`); } else if (event === SDK_READY) { readyCbCount++; } @@ -52,18 +52,18 @@ export default function sdkReadinessManagerFactory( const readyPromise = generateReadyPromise(); readinessManager.gate.once(SDK_READY_FROM_CACHE, () => { - log.i('Split SDK is ready from cache.'); + log.info('Split SDK is ready from cache.'); }); // default onRejected handler, that just logs the error, if ready promise doesn't have one. function defaultOnRejected(err: any) { - log.e(err); + log.error(err); } function generateReadyPromise() { const promise = promiseWrapper(new Promise((resolve, reject) => { readinessManager.gate.once(SDK_READY, () => { - if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.w('No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'); + if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn('No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'); resolve(); }); readinessManager.gate.once(SDK_READY_TIMED_OUT, reject); diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index 041949db..b1b7e194 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -76,10 +76,10 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl } const { treatment, label, changeNumber, config = null } = evaluation; - log.i(`Split: ${splitName}. Key: ${matchingKey}. Evaluation: ${treatment}. Label: ${label}`); + log.info(`Split: ${splitName}. Key: ${matchingKey}. Evaluation: ${treatment}. Label: ${label}`); if (validateSplitExistance(log, readinessManager, splitName, label, invokingMethodName)) { - log.i('Queueing corresponding impression.'); + log.info('Queueing corresponding impression.'); queue.push({ feature: splitName, keyName: matchingKey, diff --git a/src/sdkClient/sdkClientMethod.ts b/src/sdkClient/sdkClientMethod.ts index d89df8b7..4bb1d7ef 100644 --- a/src/sdkClient/sdkClientMethod.ts +++ b/src/sdkClient/sdkClientMethod.ts @@ -16,7 +16,7 @@ export function sdkClientMethodFactory(params: ISdkClientFactoryParams): () => S throw new Error('Shared Client not supported by the storage mechanism. Create isolated instances instead.'); } - log.d('Retrieving SDK client.'); + log.debug('Retrieving SDK client.'); return clientInstance; }; } diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index 35826036..97408161 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -41,7 +41,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? return function client(key?: SplitIO.SplitKey) { if (key === undefined) { - log.d('Retrieving default SDK client.'); + log.debug('Retrieving default SDK client.'); return mainClientInstance; } @@ -75,9 +75,9 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? sharedSyncManager.start(); - log.i('New shared client instance created.'); + log.info('New shared client instance created.'); } else { - log.d('Retrieving existing SDK client.'); + log.debug('Retrieving existing SDK client.'); } return clientInstances[instanceId]; diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index dd3230ff..8d103cf6 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -48,7 +48,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? return function client(key?: SplitIO.SplitKey, trafficType?: string) { if (key === undefined) { - log.d('Retrieving default SDK client.'); + log.debug('Retrieving default SDK client.'); return mainClientInstance; } @@ -90,9 +90,9 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? sharedSyncManager.start(); - log.i('New shared client instance created.'); + log.info('New shared client instance created.'); } else { - log.d('Retrieving existing SDK client.'); + log.debug('Retrieving existing SDK client.'); } return clientInstances[instanceId]; diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index b2bb0ed8..ace32dc0 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -79,7 +79,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. syncManager && syncManager.start(); signalListener && signalListener.start(); - log.i('New Split SDK instance created.'); + log.info('New Split SDK instance created.'); return { // Split evaluation and event tracking engine @@ -88,8 +88,8 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // Manager API to explore available information // @ts-ignore manager() { - if (managerInstance) log.i('Manager instance retrieved.'); - else log.e('Manager instance is not available. Provide the manager module on settings.'); + if (managerInstance) log.info('Manager instance retrieved.'); + else log.error('Manager instance is not available. Provide the manager module on settings.'); return managerInstance; }, diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index b176c873..a44055a6 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -22,7 +22,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I const fetch = getFetch && getFetch(); // if fetch is not available, log Error - if (!fetch) log.e(messageNoFetch + ' The SDK will not get ready.'); + if (!fetch) log.error(messageNoFetch + ' The SDK will not get ready.'); const headers: Record = { 'Accept': 'application/json', @@ -63,7 +63,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I } if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else. - log.e(`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); + log.error(`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); } // passes `undefined` as statusCode if not an HTTP error (resp === undefined) diff --git a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts index b4e1c0ac..f731821b 100644 --- a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +++ b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts @@ -23,7 +23,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { * @NOTE this method is not being used at the moment. */ clear() { - this.log.i('Flushing MySegments data from localStorage'); + this.log.info('Flushing MySegments data from localStorage'); // We cannot simply call `localStorage.clear()` since that implies removing user items from the storage // We could optimize next sentence, since it implies iterating over all localStorage items @@ -37,7 +37,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { localStorage.setItem(segmentKey, DEFINED); return true; } catch (e) { - this.log.e(e); + this.log.error(e); return false; } } @@ -49,7 +49,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { localStorage.removeItem(segmentKey); return true; } catch (e) { - this.log.e(e); + this.log.error(e); return false; } } diff --git a/src/storages/inLocalStorage/SplitsCacheInLocal.ts b/src/storages/inLocalStorage/SplitsCacheInLocal.ts index f12156c7..b84aec44 100644 --- a/src/storages/inLocalStorage/SplitsCacheInLocal.ts +++ b/src/storages/inLocalStorage/SplitsCacheInLocal.ts @@ -53,7 +53,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { } } } catch (e) { - this.log.e(e); + this.log.error(e); } } @@ -73,7 +73,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { } } } catch (e) { - this.log.e(e); + this.log.error(e); } } @@ -83,7 +83,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { * We cannot simply call `localStorage.clear()` since that implies removing user items from the storage. */ clear() { - this.log.i('Flushing Splits data from localStorage'); + this.log.info('Flushing Splits data from localStorage'); // collect item keys const len = localStorage.length; @@ -115,7 +115,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { return true; } catch (e) { - this.log.e(e); + this.log.error(e); return false; } } @@ -130,7 +130,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { return 1; } catch (e) { - this.log.e(e); + this.log.error(e); return 0; } } @@ -148,14 +148,14 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { // when using a new split query, we must update it at the store if (this.updateNewFilter) { - this.log.i('Split filter query was modified. Updating cache.'); + this.log.info('Split filter query was modified. Updating cache.'); const queryKey = this.keys.buildSplitsFilterQueryKey(); const queryString = this.splitFiltersValidation.queryString; try { if (queryString) localStorage.setItem(queryKey, queryString); else localStorage.removeItem(queryKey); } catch (e) { - this.log.e(e); + this.log.error(e); } this.updateNewFilter = false; } @@ -167,7 +167,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { this.hasSync = true; return true; } catch (e) { - this.log.e(e); + this.log.error(e); return false; } } @@ -274,7 +274,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { }); } } catch (e) { - this.log.e(e); + this.log.error(e); } } // if the filter didn't change, nothing is done diff --git a/src/storages/inLocalStorage/index.ts b/src/storages/inLocalStorage/index.ts index fa2f3fbb..0a6574f5 100644 --- a/src/storages/inLocalStorage/index.ts +++ b/src/storages/inLocalStorage/index.ts @@ -23,7 +23,7 @@ export function InLocalStorage(options: InLocalStorageOptions = {}) { // Fallback to InMemoryStorage if LocalStorage API is not available if (!isLocalStorageAvailable()) { - log.w('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); + log.warn('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); return; } diff --git a/src/storages/inRedis/EventsCacheInRedis.ts b/src/storages/inRedis/EventsCacheInRedis.ts index 13e4cc35..839faee1 100644 --- a/src/storages/inRedis/EventsCacheInRedis.ts +++ b/src/storages/inRedis/EventsCacheInRedis.ts @@ -33,7 +33,7 @@ export default class EventsCacheInRedis implements IEventsCacheAsync { // We use boolean values to signal successful queueing .then(() => true) .catch(err => { - this.log.e(`Error adding event to queue: ${err}.`); + this.log.error(`Error adding event to queue: ${err}.`); return false; }); } diff --git a/src/storages/inRedis/RedisAdapter.ts b/src/storages/inRedis/RedisAdapter.ts index 198d890f..fb7673ec 100644 --- a/src/storages/inRedis/RedisAdapter.ts +++ b/src/storages/inRedis/RedisAdapter.ts @@ -55,16 +55,16 @@ export default class RedisAdapter extends ioredis { _listenToEvents() { this.once('ready', () => { const commandsCount = this._notReadyCommandsQueue ? this._notReadyCommandsQueue.length : 0; - this.log.i(`Redis connection established. Queued commands: ${commandsCount}.`); + this.log.info(`Redis connection established. Queued commands: ${commandsCount}.`); this._notReadyCommandsQueue && this._notReadyCommandsQueue.forEach(queued => { - this.log.i(`Executing queued ${queued.name} command.`); + this.log.info(`Executing queued ${queued.name} command.`); queued.command().then(queued.resolve).catch(queued.reject); }); // After the SDK is ready for the first time we'll stop queueing commands. This is just so we can keep handling BUR for them. this._notReadyCommandsQueue = undefined; }); this.once('close', () => { - this.log.i('Redis connection closed.'); + this.log.info('Redis connection closed.'); }); } @@ -78,7 +78,7 @@ export default class RedisAdapter extends ioredis { const params = arguments; function commandWrapper() { - instance.log.d(`Executing ${method}.`); + instance.log.debug(`Executing ${method}.`); // Return original method const result = originalMethod.apply(instance, params); @@ -93,7 +93,7 @@ export default class RedisAdapter extends ioredis { result.then(cleanUpRunningCommandsCb, cleanUpRunningCommandsCb); return timeout(instance._options.operationTimeout, result).catch(err => { - instance.log.e(`${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`); + instance.log.error(`${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`); // Handling is not the adapter responsibility. throw err; }); @@ -126,19 +126,19 @@ export default class RedisAdapter extends ioredis { setTimeout(function deferedDisconnect() { if (instance._runningCommands.size > 0) { - instance.log.i(`Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`); + instance.log.info(`Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`); Promise.all(setToArray(instance._runningCommands)) .then(() => { - instance.log.d('Pending commands finished successfully, disconnecting.'); + instance.log.debug('Pending commands finished successfully, disconnecting.'); originalMethod.apply(instance, params); }) .catch(e => { - instance.log.w(`Pending commands finished with error: ${e}. Proceeding with disconnection.`); + instance.log.warn(`Pending commands finished with error: ${e}. Proceeding with disconnection.`); originalMethod.apply(instance, params); }); } else { - instance.log.d('No commands pending execution, disconnect.'); + instance.log.debug('No commands pending execution, disconnect.'); // Nothing pending, just proceed. originalMethod.apply(instance, params); } diff --git a/src/storages/inRedis/SplitsCacheInRedis.ts b/src/storages/inRedis/SplitsCacheInRedis.ts index 2a65900a..9e8d0201 100644 --- a/src/storages/inRedis/SplitsCacheInRedis.ts +++ b/src/storages/inRedis/SplitsCacheInRedis.ts @@ -83,7 +83,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { */ getSplit(name: string): Promise { if (this.redisError) { - this.log.e(this.redisError); + this.log.error(this.redisError); throw this.redisError; } @@ -137,14 +137,14 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { .then((ttCount: string | null | number) => { ttCount = parseInt(ttCount as string, 10); if (!isFiniteNumber(ttCount) || ttCount < 0) { - this.log.i(`Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`); + this.log.info(`Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`); return false; } return ttCount > 0; }) .catch(e => { - this.log.e(`Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`); + this.log.error(`Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`); // If there is an error, bypass the validation so the event can get tracked. return true; }); @@ -169,7 +169,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { */ getSplits(names: string[]): Promise> { if (this.redisError) { - this.log.e(this.redisError); + this.log.error(this.redisError); throw this.redisError; } @@ -183,7 +183,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { return Promise.resolve(splits); }) .catch(e => { - this.log.e(`Could not grab splits due to an error: ${e}.`); + this.log.error(`Could not grab splits due to an error: ${e}.`); return Promise.reject(e); }); } diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index 94a65654..6f06e553 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -48,7 +48,7 @@ function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILog try { data = fs.readFileSync(filePath, 'utf-8'); } catch (e) { - log.e(e.message); + log.error(e.message); return {}; } @@ -60,12 +60,12 @@ function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILog let tuple: string | string[] = line.trim(); if (tuple === '' || tuple.charAt(0) === '#') { - log.d(`Ignoring empty line or comment at #${index}`); + log.debug(`Ignoring empty line or comment at #${index}`); } else { tuple = tuple.split(/\s+/); if (tuple.length !== 2) { - log.d(`Ignoring line since it does not have exactly two columns #${index}`); + log.debug(`Ignoring line since it does not have exactly two columns #${index}`); } else { const splitName = tuple[SPLIT_POSITION]; const condition = parseCondition({ treatment: tuple[TREATMENT_POSITION] }); @@ -92,7 +92,7 @@ function readYAMLConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILogg yamldoc = yaml.safeLoad(data); } catch (e) { - log.e(e); + log.error(e); return {}; } @@ -102,7 +102,7 @@ function readYAMLConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILogg const splitName = Object.keys(splitEntry)[0]; if (!splitName || !isString(splitEntry[splitName].treatment)) - log.e('Ignoring entry on YAML since the format is incorrect.'); + log.error('Ignoring entry on YAML since the format is incorrect.'); const mockData = splitEntry[splitName]; @@ -167,7 +167,7 @@ export default function splitsParserFromFile({ features, log }: { features?: Spl // If we have a filePath, it means the extension is correct, choose the parser. if (endsWith(filePath, '.split')) { - log.w('.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'); + log.warn('.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'); mockData = readSplitConfigFile(filePath, log); } else { mockData = readYAMLConfigFile(filePath, log); diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index ef27ac78..a2b1eb47 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -30,12 +30,12 @@ export function fromObjectUpdaterFactory( splitsMock = splitsParser(settings); } catch (err) { loadError = err; - log.e(`There was an issue loading the mock Splits data, no changes will be applied to the current cache. ${err}`); + log.error(`There was an issue loading the mock Splits data, no changes will be applied to the current cache. ${err}`); } if (!loadError && splitsMock) { - log.d('Splits data: '); - log.d(JSON.stringify(splitsMock)); + log.debug('Splits data: '); + log.debug(JSON.stringify(splitsMock)); forOwn(splitsMock, function (val, name) { splits.push([ diff --git a/src/sync/polling/pollingManagerCS.ts b/src/sync/polling/pollingManagerCS.ts index 1dc0c7b0..54c399db 100644 --- a/src/sync/polling/pollingManagerCS.ts +++ b/src/sync/polling/pollingManagerCS.ts @@ -48,7 +48,7 @@ export default function pollingManagerCSFactory( if (!splitsSyncTask.isRunning()) return; // noop if not doing polling const splitsHaveSegments = storage.splits.usesSegments(); if (splitsHaveSegments !== mySegmentsSyncTask.isRunning()) { - log.i(`Turning segments data polling ${splitsHaveSegments ? 'ON' : 'OFF'}.`); + log.info(`Turning segments data polling ${splitsHaveSegments ? 'ON' : 'OFF'}.`); if (splitsHaveSegments) { startMySegmentsSyncTasks(); } else { @@ -77,7 +77,7 @@ export default function pollingManagerCSFactory( // Start periodic fetching (polling) start() { - log.i('Starting polling'); + log.info('Starting polling'); splitsSyncTask.start(); if (storage.splits.usesSegments()) startMySegmentsSyncTasks(); @@ -85,7 +85,7 @@ export default function pollingManagerCSFactory( // Stop periodic fetching (polling) stop() { - log.i('Stopping polling'); + log.info('Stopping polling'); if (splitsSyncTask.isRunning()) splitsSyncTask.stop(); stopMySegmentsSyncTasks(); diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index 4ab0aab5..ee4ddcf2 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -30,9 +30,9 @@ export default function pollingManagerSSFactory( // Start periodic fetching (polling) start() { - log.i('Starting polling'); - log.d(`Splits will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`); - log.d(`Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`); + log.info('Starting polling'); + log.debug(`Splits will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`); + log.debug(`Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`); const startingUp = splitsSyncTask.start(); if (thenable(startingUp)) { @@ -44,7 +44,7 @@ export default function pollingManagerSSFactory( // Stop periodic fetching (polling) stop() { - log.i('Stopping polling'); + log.info('Stopping polling'); if (splitsSyncTask.isRunning()) splitsSyncTask.stop(); if (segmentsSyncTask.isRunning()) segmentsSyncTask.stop(); diff --git a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts index 3ff393e4..9859c48e 100644 --- a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts @@ -74,7 +74,7 @@ function mySegmentsUpdaterFactory( if (startingUp && retriesOnFailureBeforeReady > retry) { retry += 1; - log.w(`Retrying download of segments #${retry}. Reason: ${error}`); + log.warn(`Retrying download of segments #${retry}. Reason: ${error}`); return _mySegmentsUpdater(retry); } else { startingUp = false; diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index 906ce181..90cefe37 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -46,7 +46,7 @@ function segmentChangesUpdaterFactory( * @param {string[] | undefined} segmentNames list of segment names to fetch. By passing `undefined` it fetches the list of segments registered at the storage */ return function segmentChangesUpdater(segmentNames?: string[]) { - log.d('Started segments update'); + log.debug('Started segments update'); // If not a segment name provided, read list of available segments names to be updated. if (!segmentNames) segmentNames = segmentsCache.getRegisteredSegments(); @@ -58,7 +58,7 @@ function segmentChangesUpdaterFactory( const segmentName = segmentNames[index]; const since = segmentsCache.getChangeNumber(segmentName); - log.d(`Processing segment ${segmentName}`); + log.debug(`Processing segment ${segmentName}`); updaters.push(segmentChangesFetcher(since, segmentName, _promiseDecorator).then(function (changes) { let changeNumber = -1; @@ -70,7 +70,7 @@ function segmentChangesUpdaterFactory( changeNumber = x.till; } - log.d(`Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`); + log.debug(`Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`); }); return changeNumber; @@ -94,7 +94,7 @@ function segmentChangesUpdaterFactory( if (error.statusCode === 403) { // @TODO although factory status is destroyed, synchronization is not stopped readiness.destroy(); - log.e('Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'); + log.error('Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'); } return false; diff --git a/src/sync/polling/syncTasks/splitsSyncTask.ts b/src/sync/polling/syncTasks/splitsSyncTask.ts index ce3fb1dc..a650ca4c 100644 --- a/src/sync/polling/syncTasks/splitsSyncTask.ts +++ b/src/sync/polling/syncTasks/splitsSyncTask.ts @@ -103,7 +103,7 @@ export function splitChangesUpdaterFactory( * @param {number} retry current number of retry attemps */ function _splitChangesUpdater(since: number, retry = 0): Promise { - log.d(`Spin up split update using since = ${since}`); + log.debug(`Spin up split update using since = ${since}`); const fetcherPromise = splitChangesFetcher(since, _promiseDecorator) .then((splitChanges: ISplitChangesResponse) => { @@ -111,9 +111,9 @@ export function splitChangesUpdaterFactory( const mutation = computeSplitsMutation(splitChanges.splits); - log.d(`New splits ${mutation.added.length}`); - log.d(`Removed splits ${mutation.removed.length}`); - log.d(`Segment names collected ${mutation.segments.length}`); + log.debug(`New splits ${mutation.added.length}`); + log.debug(`Removed splits ${mutation.removed.length}`); + log.debug(`Segment names collected ${mutation.segments.length}`); // Write into storage // @TODO if allowing custom storages, wrap errors as SplitErrors to distinguish from user callback errors @@ -138,11 +138,11 @@ export function splitChangesUpdaterFactory( startingUp = false; // Stop retrying. } - log.w(`Error while doing fetch of Splits. ${error}`); + log.warn(`Error while doing fetch of Splits. ${error}`); if (startingUp && retriesOnFailureBeforeReady && retriesOnFailureBeforeReady > retry) { retry += 1; - log.i(`Retrying download of splits #${retry}. Reason: ${error}`); + log.info(`Retrying download of splits #${retry}. Reason: ${error}`); return _splitChangesUpdater(since, retry); } else { startingUp = false; diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index f3699f5a..c81edefa 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -28,7 +28,7 @@ export default function SSEHandlerFactory(pushEmitter: IPushEventEmitter, log: I try { errorWithParsedData = errorParser(error); } catch (err) { - log.w(`Error parsing SSE error notification: ${err}`); + log.warn(`Error parsing SSE error notification: ${err}`); } pushEmitter.emit(SSE_ERROR, errorWithParsedData); @@ -40,12 +40,12 @@ export default function SSEHandlerFactory(pushEmitter: IPushEventEmitter, log: I try { messageWithParsedData = messageParser(message); } catch (err) { - log.w(`Error parsing new SSE message notification: ${err}`); + log.warn(`Error parsing new SSE message notification: ${err}`); return; } const { parsedData, data, channel, timestamp } = messageWithParsedData; - log.d(`New SSE message received, with data: ${data}.`); + log.debug(`New SSE message received, with data: ${data}.`); // we only handle update events if streaming is up. if (!notificationKeeper.isStreamingUp() && parsedData.type !== OCCUPANCY && parsedData.type !== CONTROL) diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index b6f3e501..57e4fcb7 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -41,7 +41,7 @@ export default function pushManagerFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.w(e + 'Falling back to polling mode.'); + log.warn(e + 'Falling back to polling mode.'); return; } const authenticate = authenticateFactory(fetchAuth); @@ -90,14 +90,14 @@ export default function pushManagerFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.i(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.i('Connecting to push streaming.'); + log.info('Connecting to push streaming.'); const userKeys = userKey ? Object.keys(workers) : undefined; authenticate(userKeys).then( @@ -110,7 +110,7 @@ export default function pushManagerFactory( // emit PUSH_DISCONNECT if org is not whitelisted if (!authData.pushEnabled) { - log.i('Streaming is not available. Switching to polling mode.'); + log.info('Streaming is not available. Switching to polling mode.'); pushEmitter.emit(PUSH_DISCONNECT); // there is no need to close sseClient (it is not open on this scenario) return; } @@ -134,13 +134,13 @@ export default function pushManagerFactory( // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { - log.e(errorMessage); + log.error(errorMessage); return; } // Handle other HTTP and network errors const delayInMillis = reauthBackoff.scheduleCall(); - log.e(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); + log.error(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); } ); } @@ -148,7 +148,7 @@ export default function pushManagerFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.i('Disconnecting from push streaming.'); + log.info('Disconnecting from push streaming.'); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -187,7 +187,7 @@ export default function pushManagerFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.error(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index a669f961..cae03a58 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -39,7 +39,7 @@ export default function pushManagerCSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.w(e + 'Falling back to polling mode.'); + log.warn(e + 'Falling back to polling mode.'); return; } const authenticate = authenticateFactory(fetchAuth); @@ -86,14 +86,14 @@ export default function pushManagerCSFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.i(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.i('Connecting to push streaming.'); + log.info('Connecting to push streaming.'); const userKeys = Object.keys(workers); // [Only for client-side] authenticate(userKeys).then( @@ -106,7 +106,7 @@ export default function pushManagerCSFactory( // emit PUSH_DISCONNECT if org is not whitelisted if (!authData.pushEnabled) { - log.i('Streaming is not available. Switching to polling mode.'); + log.info('Streaming is not available. Switching to polling mode.'); pushEmitter.emit(PUSH_DISCONNECT); // there is no need to close sseClient (it is not open on this scenario) return; } @@ -130,13 +130,13 @@ export default function pushManagerCSFactory( // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { - log.e(errorMessage); + log.error(errorMessage); return; } // Handle other HTTP and network errors const delayInMillis = reauthBackoff.scheduleCall(); - log.e(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); + log.error(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); } ); } @@ -144,7 +144,7 @@ export default function pushManagerCSFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.i('Disconnecting from push streaming.'); + log.info('Disconnecting from push streaming.'); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -182,7 +182,7 @@ export default function pushManagerCSFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.error(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index f2ba56c8..eab958d6 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -35,7 +35,7 @@ export default function pushManagerSSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.w(e + 'Falling back to polling mode.'); + log.warn(e + 'Falling back to polling mode.'); return; } const authenticate = authenticateFactory(fetchAuth); @@ -67,14 +67,14 @@ export default function pushManagerSSFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.i(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.i('Connecting to push streaming.'); + log.info('Connecting to push streaming.'); authenticate().then( function (authData) { @@ -86,7 +86,7 @@ export default function pushManagerSSFactory( // emit PUSH_DISCONNECT if org is not whitelisted if (!authData.pushEnabled) { - log.i('Streaming is not available. Switching to polling mode.'); + log.info('Streaming is not available. Switching to polling mode.'); pushEmitter.emit(PUSH_DISCONNECT); // there is no need to close sseClient (it is not open on this scenario) return; } @@ -107,13 +107,13 @@ export default function pushManagerSSFactory( // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { - log.e(errorMessage); + log.error(errorMessage); return; } // Handle other HTTP and network errors const delayInMillis = reauthBackoff.scheduleCall(); - log.e(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); + log.error(`${errorMessage}. Attempting to reauthenticate in ${delayInMillis / 1000} seconds.`); } ); } @@ -121,7 +121,7 @@ export default function pushManagerSSFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.i('Disconnecting from push streaming.'); + log.info('Disconnecting from push streaming.'); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -159,7 +159,7 @@ export default function pushManagerSSFactory( } const errorMessage = error.parsedData && error.parsedData.message; - log.e(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.error(`Fail to connect to streaming${errorMessage ? `, with error message: "${errorMessage}"` : ''}. Attempting to reconnect in ${delayInMillis / 1000} seconds.`); pushEmitter.emit(PUSH_DISCONNECT); // no harm if polling already }); diff --git a/src/sync/submitters/eventsSyncTask.ts b/src/sync/submitters/eventsSyncTask.ts index d0d3d235..9f91f2be 100644 --- a/src/sync/submitters/eventsSyncTask.ts +++ b/src/sync/submitters/eventsSyncTask.ts @@ -37,7 +37,7 @@ export function eventsSyncTaskFactory( // register eventsSubmitter to be executed when events cache is full eventsCache.setOnFullQueueCb(() => { - log.i('Flushing full events queue and reseting timer.'); + log.info('Flushing full events queue and reseting timer.'); syncTask.execute(); }); diff --git a/src/sync/submitters/submitterSyncTask.ts b/src/sync/submitters/submitterSyncTask.ts index 3a087954..5da26e1a 100644 --- a/src/sync/submitters/submitterSyncTask.ts +++ b/src/sync/submitters/submitterSyncTask.ts @@ -27,7 +27,7 @@ export function submitterSyncTaskFactory( const data = sourceCache.state(); const dataCount: number | '' = typeof data.length === 'number' ? data.length : ''; - log.i(`Pushing ${dataCount} ${dataName}.`); + log.info(`Pushing ${dataCount} ${dataName}.`); const latencyTrackerStop = latencyTracker && latencyTracker.start(); const jsonPayload = JSON.stringify(fromCacheToPayload ? fromCacheToPayload(data) : data); @@ -38,14 +38,14 @@ export function submitterSyncTaskFactory( sourceCache.clear(); // we clear the queue if request successes. }).catch(err => { if (!maxRetries) { - log.w(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); + log.warn(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); } else if (retries === maxRetries) { retries = 0; sourceCache.clear(); // we clear the queue if request fails after retries. - log.w(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); + log.warn(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); } else { retries++; - log.w(`Failed to push ${dataCount} ${dataName}, keeping data to retry on next iteration. Reason ${err}.`); + log.warn(`Failed to push ${dataCount} ${dataName}, keeping data to retry on next iteration. Reason ${err}.`); } }); diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index 72a94c22..64605039 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -60,15 +60,15 @@ export function syncManagerOnlineFactory( function startPolling() { if (!pollingManager.isRunning()) { - log.i('Streaming not available. Starting periodic fetch of data.'); + log.info('Streaming not available. Starting periodic fetch of data.'); pollingManager.start(); } else { - log.i('Streaming couldn\'t connect. Continue periodic fetch of data.'); + log.info('Streaming couldn\'t connect. Continue periodic fetch of data.'); } } function stopPollingAndSyncAll() { - log.i('PUSH (re)connected. Syncing and stopping periodic fetch of data.'); + log.info('PUSH (re)connected. Syncing and stopping periodic fetch of data.'); // if polling, stop if (pollingManager.isRunning()) pollingManager.stop(); diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index 8b8dc3a2..ea74759e 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -17,7 +17,7 @@ export default function syncTaskFactory(task: (...a function execute(...args: Input) { executing = true; - log.d(`Running ${taskName}`); + log.debug(`Running ${taskName}`); return task(...args).then(result => { executing = false; if (running) timeoutID = setTimeout(execute, period, ...args); @@ -35,7 +35,7 @@ export default function syncTaskFactory(task: (...a start(...args: Input) { if (!running) { running = true; - log.d(`Starting ${taskName}. Running each ${period} millis`); + log.debug(`Starting ${taskName}. Running each ${period} millis`); return execute(...args); } }, @@ -43,7 +43,7 @@ export default function syncTaskFactory(task: (...a stop() { running = false; if (timeoutID) { - log.d(`Stopping ${taskName}`); + log.debug(`Stopping ${taskName}`); clearTimeout(timeoutID); timeoutID = undefined; } diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index 9c533f3d..9e200705 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -25,7 +25,7 @@ export default function eventTrackerFactory( const msg = `event of type "${eventTypeId}" for traffic type "${trafficTypeName}". Key: ${key}. Value: ${value}. Timestamp: ${timestamp}. ${properties ? 'With properties.' : 'With no properties.'}`; if (tracked) { - log.i(`Successfully qeued ${msg}`); + log.info(`Successfully qeued ${msg}`); if (integrationsManager) { // Wrap in a timeout because we don't want it to be blocking. setTimeout(function () { @@ -37,7 +37,7 @@ export default function eventTrackerFactory( }, 0); } } else { - log.w(`Failed to queue ${msg}`); + log.warn(`Failed to queue ${msg}`); } return tracked; diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index 9c48a4d3..d5144065 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -64,9 +64,9 @@ export default function impressionsTrackerFactory( // If we're on an async storage, handle error and log it. if (thenable(res)) { res.then(() => { - log.d(`Successfully stored ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}.`); + log.debug(`Successfully stored ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}.`); }).catch(err => { - log.e(`Could not store impressions bulk with ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}. Error: ${err}`); + log.error(`Could not store impressions bulk with ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}. Error: ${err}`); }); } @@ -90,7 +90,7 @@ export default function impressionsTrackerFactory( try { // An exception on the listeners should not break the SDK. if (impressionListener) impressionListener.logImpression(impressionData); } catch (err) { - log.e(`Impression listener logImpression method threw: ${err}.`); + log.error(`Impression listener logImpression method threw: ${err}.`); } }, 0); } diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index b8d804e6..5af87568 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -12,14 +12,14 @@ function apiKeyError(reason: string) { return `Factory instantiation: ${reason}, export function validateApiKey(log: ILogger, maybeApiKey: any): string | false { let apiKey: string | false = false; if (maybeApiKey == undefined) { // eslint-disable-line eqeqeq - log.e(apiKeyError('you passed a null or undefined api_key')); + log.error(apiKeyError('you passed a null or undefined api_key')); } else if (isString(maybeApiKey)) { if (maybeApiKey.length > 0) apiKey = maybeApiKey; else - log.e(apiKeyError('you passed an empty api_key')); + log.error(apiKeyError('you passed an empty api_key')); } else { - log.e(apiKeyError('you passed an invalid api_key')); + log.error(apiKeyError('you passed an invalid api_key')); } return apiKey; @@ -39,10 +39,10 @@ export function validateAndTrackApiKey(log: ILogger, maybeApiKey: any): string | // If this key is not present, only warning scenarios is that we have factories for other keys. usedKeysMap[apiKey] = 1; if (Object.keys(usedKeysMap).length > 1) { - log.w(apiKeyWarn('You already have an instance of the Split factory. Make sure you definitely want this additional instance')); + log.warn(apiKeyWarn('You already have an instance of the Split factory. Make sure you definitely want this additional instance')); } } else { - log.w(apiKeyWarn(`You already have ${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key`)); + log.warn(apiKeyWarn(`You already have ${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key`)); usedKeysMap[apiKey]++; } } diff --git a/src/utils/inputValidation/attributes.ts b/src/utils/inputValidation/attributes.ts index c2265810..0a938c64 100644 --- a/src/utils/inputValidation/attributes.ts +++ b/src/utils/inputValidation/attributes.ts @@ -9,6 +9,6 @@ export function validateAttributes(log: ILogger, maybeAttrs: any, method: string if (isObject(maybeAttrs) || maybeAttrs == undefined) // eslint-disable-line eqeqeq return maybeAttrs; - log.e(`${method}: attributes must be a plain object.`); + log.error(`${method}: attributes must be a plain object.`); return false; } diff --git a/src/utils/inputValidation/event.ts b/src/utils/inputValidation/event.ts index cb4b774c..716661a3 100644 --- a/src/utils/inputValidation/event.ts +++ b/src/utils/inputValidation/event.ts @@ -7,14 +7,14 @@ const EVENT_TYPE_REGEX = /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/; export function validateEvent(log: ILogger, maybeEvent: any, method: string): string | false { if (maybeEvent == undefined) { // eslint-disable-line eqeqeq - log.e(`${method}: you passed a null or undefined event_type, event_type must be a non-empty string.`); + log.error(`${method}: you passed a null or undefined event_type, event_type must be a non-empty string.`); } else if (!isString(maybeEvent)) { - log.e(`${method}: you passed an invalid event_type, event_type must be a non-empty string.`); + log.error(`${method}: you passed an invalid event_type, event_type must be a non-empty string.`); } else { // It is a string. if (maybeEvent.length === 0) { - log.e(`${method}: you passed an empty event_type, event_type must be a non-empty string.`); + log.error(`${method}: you passed an empty event_type, event_type must be a non-empty string.`); } else if (!EVENT_TYPE_REGEX.test(maybeEvent)) { - log.e(`${method}: you passed "${maybeEvent}", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.`); + log.error(`${method}: you passed "${maybeEvent}", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.`); } else { return maybeEvent; } diff --git a/src/utils/inputValidation/eventProperties.ts b/src/utils/inputValidation/eventProperties.ts index 99051d72..7a1e4e57 100644 --- a/src/utils/inputValidation/eventProperties.ts +++ b/src/utils/inputValidation/eventProperties.ts @@ -18,7 +18,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth if (maybeProperties == undefined) return { properties: null, size: BASE_EVENT_SIZE }; // eslint-disable-line eqeqeq if (!isObject(maybeProperties)) { - log.e(`${method}: properties must be a plain object.`); + log.error(`${method}: properties must be a plain object.`); return { properties: false, size: BASE_EVENT_SIZE }; } @@ -31,7 +31,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth }; if (keys.length > MAX_PROPERTIES_AMOUNT) { - log.w(`${method}: Event has more than 300 properties. Some of them will be trimmed when processed.`); + log.warn(`${method}: Event has more than 300 properties. Some of them will be trimmed when processed.`); } for (let i = 0; i < keys.length; i++) { @@ -48,7 +48,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth clone[keys[i]] = null; val = null; isNullVal = true; - log.w(`${method}: Property ${keys[i]} is of invalid type. Setting value to null.`); + log.warn(`${method}: Property ${keys[i]} is of invalid type. Setting value to null.`); } if (isNullVal) output.size += ECMA_SIZES.NULL; @@ -57,7 +57,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth else if (isStringVal) output.size += val.length * ECMA_SIZES.STRING; if (output.size > MAX_PROPERTIES_SIZE) { - log.e(`${method}: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.`); + log.error(`${method}: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.`); output.properties = false; break; } diff --git a/src/utils/inputValidation/eventValue.ts b/src/utils/inputValidation/eventValue.ts index ef65b656..5b3387da 100644 --- a/src/utils/inputValidation/eventValue.ts +++ b/src/utils/inputValidation/eventValue.ts @@ -7,6 +7,6 @@ export function validateEventValue(log: ILogger, maybeValue: any, method: string if (isFiniteNumber(maybeValue) || maybeValue == undefined) // eslint-disable-line eqeqeq return maybeValue; - log.e(`${method}: value must be a finite number.`); + log.error(`${method}: value must be a finite number.`); return false; } diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index f9028593..38b08e38 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -6,13 +6,13 @@ import { IReadinessManager } from '../../readiness/types'; export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadinessManager): boolean { if (!readinessManager.isDestroyed()) return true; - log.e('Client has already been destroyed - no calls possible.'); + log.error('Client has already been destroyed - no calls possible.'); return false; } export function validateIfOperational(log: ILogger, readinessManager: IReadinessManager, method: string) { if (readinessManager.isReady() || readinessManager.isReadyFromCache()) return true; - log.w(`${method}: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.`); + log.warn(`${method}: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.`); return false; } diff --git a/src/utils/inputValidation/key.ts b/src/utils/inputValidation/key.ts index 42059b07..d37a0363 100644 --- a/src/utils/inputValidation/key.ts +++ b/src/utils/inputValidation/key.ts @@ -8,11 +8,11 @@ const KEY_MAX_LENGTH = 250; function validateKeyValue(log: ILogger, maybeKey: any, method: string, type: string): string | false { if (maybeKey == undefined) { // eslint-disable-line eqeqeq - log.e(`${method}: you passed a null or undefined ${type}, ${type} must be a non-empty string.`); + log.error(`${method}: you passed a null or undefined ${type}, ${type} must be a non-empty string.`); return false; } if (isFiniteNumber(maybeKey)) { - log.w(`${method}: ${type} "${maybeKey}" is not of type string, converting.`); + log.warn(`${method}: ${type} "${maybeKey}" is not of type string, converting.`); return toString(maybeKey); } if (isString(maybeKey)) { @@ -23,12 +23,12 @@ function validateKeyValue(log: ILogger, maybeKey: any, method: string, type: str if (maybeKey.length > 0 && maybeKey.length <= KEY_MAX_LENGTH) return maybeKey; if (maybeKey.length === 0) { - log.e(`${method}: you passed an empty string, ${type} must be a non-empty string.`); + log.error(`${method}: you passed an empty string, ${type} must be a non-empty string.`); } else if (maybeKey.length > KEY_MAX_LENGTH) { - log.e(`${method}: ${type} too long, ${type} must be 250 characters or less.`); + log.error(`${method}: ${type} too long, ${type} must be 250 characters or less.`); } } else { - log.e(`${method}: you passed an invalid ${type} type, ${type} must be a non-empty string.`); + log.error(`${method}: you passed an invalid ${type} type, ${type} must be a non-empty string.`); } return false; @@ -44,7 +44,7 @@ export function validateKey(log: ILogger, maybeKey: any, method: string): SplitI matchingKey, bucketingKey }; - log.e(`${method}: Key must be an object with bucketingKey and matchingKey with valid string properties.`); + log.error(`${method}: Key must be an object with bucketingKey and matchingKey with valid string properties.`); return false; } else { return validateKeyValue(log, maybeKey, method, 'key'); diff --git a/src/utils/inputValidation/preloadedData.ts b/src/utils/inputValidation/preloadedData.ts index 769cc083..fd1ae877 100644 --- a/src/utils/inputValidation/preloadedData.ts +++ b/src/utils/inputValidation/preloadedData.ts @@ -7,18 +7,18 @@ import { ILogger } from '../../logger/types'; function validateTimestampData(log: ILogger, maybeTimestamp: any, method: string, item: string) { if (isFiniteNumber(maybeTimestamp) && maybeTimestamp > -1) return true; - log.e(`${method}: preloadedData.${item} must be a positive number.`); + log.error(`${method}: preloadedData.${item} must be a positive number.`); return false; } function validateSplitsData(log: ILogger, maybeSplitsData: any, method: string) { if (isObject(maybeSplitsData)) { const splitNames = Object.keys(maybeSplitsData); - if (splitNames.length === 0) log.w(`${method}: preloadedData.splitsData doesn't contain split definitions.`); + if (splitNames.length === 0) log.warn(`${method}: preloadedData.splitsData doesn't contain split definitions.`); // @TODO in the future, consider handling the possibility of having parsed definitions of splits if (splitNames.every(splitName => validateSplit(log, splitName, method) && isString(maybeSplitsData[splitName]))) return true; } - log.e(`${method}: preloadedData.splitsData must be a map of split names to their serialized definitions.`); + log.error(`${method}: preloadedData.splitsData must be a map of split names to their serialized definitions.`); return false; } @@ -31,7 +31,7 @@ function validateMySegmentsData(log: ILogger, maybeMySegmentsData: any, method: return Array.isArray(segmentNames) && segmentNames.every(segmentName => isString(segmentName)); })) return true; } - log.e(`${method}: preloadedData.mySegmentsData must be a map of user keys to their list of segment names.`); + log.error(`${method}: preloadedData.mySegmentsData must be a map of user keys to their list of segment names.`); return false; } @@ -40,13 +40,13 @@ function validateSegmentsData(log: ILogger, maybeSegmentsData: any, method: stri const segmentNames = Object.keys(maybeSegmentsData); if (segmentNames.every(segmentName => isString(maybeSegmentsData[segmentName]))) return true; } - log.e(`${method}: preloadedData.segmentsData must be a map of segment names to their serialized definitions.`); + log.error(`${method}: preloadedData.segmentsData must be a map of segment names to their serialized definitions.`); return false; } export function validatePreloadedData(log: ILogger, maybePreloadedData: any, method: string): maybePreloadedData is SplitIO.PreloadedData { if (!isObject(maybePreloadedData)) { - log.e(`${method}: preloadedData must be an object.`); + log.error(`${method}: preloadedData must be an object.`); } else if ( validateTimestampData(log, maybePreloadedData.lastUpdated, method, 'lastUpdated') && validateTimestampData(log, maybePreloadedData.since, method, 'since') && diff --git a/src/utils/inputValidation/split.ts b/src/utils/inputValidation/split.ts index ef5471dd..aefa4323 100644 --- a/src/utils/inputValidation/split.ts +++ b/src/utils/inputValidation/split.ts @@ -8,19 +8,19 @@ const TRIMMABLE_SPACES_REGEX = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/; export function validateSplit(log: ILogger, maybeSplit: any, method: string, item = 'split name'): string | false { if (maybeSplit == undefined) { // eslint-disable-line eqeqeq - log.e(`${method}: you passed a null or undefined ${item}, ${item} must be a non-empty string.`); + log.error(`${method}: you passed a null or undefined ${item}, ${item} must be a non-empty string.`); } else if (!isString(maybeSplit)) { - log.e(`${method}: you passed an invalid ${item}, ${item} must be a non-empty string.`); + log.error(`${method}: you passed an invalid ${item}, ${item} must be a non-empty string.`); } else { if (TRIMMABLE_SPACES_REGEX.test(maybeSplit)) { - log.w(`${method}: ${item} "${maybeSplit}" has extra whitespace, trimming.`); + log.warn(`${method}: ${item} "${maybeSplit}" has extra whitespace, trimming.`); maybeSplit = maybeSplit.trim(); } if (maybeSplit.length > 0) { return maybeSplit; } else { - log.e(`${method}: you passed an empty ${item}, ${item} must be a non-empty string.`); + log.error(`${method}: you passed an empty ${item}, ${item} must be a non-empty string.`); } } diff --git a/src/utils/inputValidation/splitExistance.ts b/src/utils/inputValidation/splitExistance.ts index 7b3bc616..f3f3f3fc 100644 --- a/src/utils/inputValidation/splitExistance.ts +++ b/src/utils/inputValidation/splitExistance.ts @@ -11,7 +11,7 @@ import { ILogger } from '../../logger/types'; export function validateSplitExistance(log: ILogger, readinessManager: IReadinessManager, splitName: string, labelOrSplitObj: any, method: string): boolean { if (readinessManager.isReady()) { // Only if it's ready we validate this, otherwise it may just be that the SDK is not ready yet. if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj == null) { - log.w(`${method}: you passed "${splitName}" that does not exist in this environment, please double check what Splits exist in the web console.`); + log.warn(`${method}: you passed "${splitName}" that does not exist in this environment, please double check what Splits exist in the web console.`); return false; } } diff --git a/src/utils/inputValidation/splits.ts b/src/utils/inputValidation/splits.ts index fb46528b..2a333ee8 100644 --- a/src/utils/inputValidation/splits.ts +++ b/src/utils/inputValidation/splits.ts @@ -17,6 +17,6 @@ export function validateSplits(log: ILogger, maybeSplits: any, method: string, l if (validatedArray.length) return uniq(validatedArray); } - log.e(`${method}: ${listName} must be a non-empty array.`); + log.error(`${method}: ${listName} must be a non-empty array.`); return false; } diff --git a/src/utils/inputValidation/trafficType.ts b/src/utils/inputValidation/trafficType.ts index 377569f0..d287f00c 100644 --- a/src/utils/inputValidation/trafficType.ts +++ b/src/utils/inputValidation/trafficType.ts @@ -7,15 +7,15 @@ const CAPITAL_LETTERS_REGEX = /[A-Z]/; export function validateTrafficType(log: ILogger, maybeTT: any, method: string): string | false { if (maybeTT == undefined) { // eslint-disable-line eqeqeq - log.e(`${method}: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.`); + log.error(`${method}: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.`); } else if (!isString(maybeTT)) { - log.e(`${method}: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.`); + log.error(`${method}: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.`); } else { if (maybeTT.length === 0) { - log.e(`${method}: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.`); + log.error(`${method}: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.`); } else { if (CAPITAL_LETTERS_REGEX.test(maybeTT)) { - log.w(`${method}: traffic_type_name should be all lowercase - converting string to lowercase.`); + log.warn(`${method}: traffic_type_name should be all lowercase - converting string to lowercase.`); maybeTT = maybeTT.toLowerCase(); } diff --git a/src/utils/inputValidation/trafficTypeExistance.ts b/src/utils/inputValidation/trafficTypeExistance.ts index 879dd0b6..1fbc3601 100644 --- a/src/utils/inputValidation/trafficTypeExistance.ts +++ b/src/utils/inputValidation/trafficTypeExistance.ts @@ -9,7 +9,7 @@ import { ILogger } from '../../logger/types'; // const log = logFactory(''); function logTTExistanceWarning(log: ILogger, maybeTT: string, method: string) { - log.w(`${method}: Traffic Type ${maybeTT} does not have any corresponding Splits in this environment, make sure you're tracking your events to a valid traffic type defined in the Split console.`); + log.warn(`${method}: Traffic Type ${maybeTT} does not have any corresponding Splits in this environment, make sure you're tracking your events to a valid traffic type defined in the Split console.`); } /** diff --git a/src/utils/settingsValidation/impressionsMode.ts b/src/utils/settingsValidation/impressionsMode.ts index d927e179..48c3bb65 100644 --- a/src/utils/settingsValidation/impressionsMode.ts +++ b/src/utils/settingsValidation/impressionsMode.ts @@ -7,7 +7,7 @@ import { DEBUG, OPTIMIZED } from '../constants'; export default function validImpressionsMode(log: ILogger, impressionsMode: string): SplitIO.ImpressionsMode { impressionsMode = impressionsMode.toUpperCase(); if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) === -1) { - log.e(`You passed an invalid impressionsMode, impressionsMode should be one of the following values: '${DEBUG}' or '${OPTIMIZED}'. Defaulting to '${OPTIMIZED}' mode.`); + log.error(`You passed an invalid impressionsMode, impressionsMode should be one of the following values: '${DEBUG}' or '${OPTIMIZED}'. Defaulting to '${OPTIMIZED}' mode.`); impressionsMode = OPTIMIZED; } diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index d0703bd7..7ebafbf8 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -21,7 +21,7 @@ export function validateIntegrations(settings: any, integrationValidator: (integ // Log a warning if at least one item is invalid const invalids = integrations.length - validIntegrations.length; - if (invalids) settings.log.w(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); + if (invalids) settings.log.warn(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); return validIntegrations; } diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index a8b38085..4d25db12 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -97,12 +97,12 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: if (!maybeSplitFilters) return res; // Warn depending on the mode if (mode !== STANDALONE_MODE) { - log.w(`Factory instantiation: split filters have been configured but will have no effect if mode is not '${STANDALONE_MODE}', since synchronization is being deferred to an external tool.`); + log.warn(`Factory instantiation: split filters have been configured but will have no effect if mode is not '${STANDALONE_MODE}', since synchronization is being deferred to an external tool.`); return res; } // Check collection type if (!Array.isArray(maybeSplitFilters) || maybeSplitFilters.length === 0) { - log.w('Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'); + log.warn('Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'); return res; } @@ -113,7 +113,7 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: res.groupedFilters[filter.type as SplitIO.SplitFilterType] = res.groupedFilters[filter.type as SplitIO.SplitFilterType].concat(filter.values); return true; } else { - log.w(`Factory instantiation: split filter at position '${index}' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'.`); + log.warn(`Factory instantiation: split filter at position '${index}' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'.`); } return false; }); @@ -125,7 +125,7 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: // build query string res.queryString = queryStringBuilder(res.groupedFilters); - log.d(`Factory instantiation: splits filtering criteria is '${res.queryString}'.`); + log.debug(`Factory instantiation: splits filtering criteria is '${res.queryString}'.`); return res; } diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index f1b74717..f5300b9f 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -17,7 +17,7 @@ export function validateStorageCS(settings: any): ISettings['storage'] { // @TODO validate its API (Splits cache, MySegments cache, etc) when supporting custom storages if (storage) { if (typeof storage === 'function') return storage; - settings.log.w('The provided storage is invalid. Fallbacking into default MEMORY storage'); + settings.log.warn('The provided storage is invalid. Fallbacking into default MEMORY storage'); } // return default InMemory storage if provided one is not valid diff --git a/src/utils/timeTracker/index.ts b/src/utils/timeTracker/index.ts index f3974bbc..fa2dccb3 100644 --- a/src/utils/timeTracker/index.ts +++ b/src/utils/timeTracker/index.ts @@ -205,7 +205,7 @@ const TrackerAPI = { if (timerData) { // Stop the timer and round result for readability. const et = timerData.timer(); - logger.d(`[${task}] took ${et}ms to finish.`); + logger.debug(`[${task}] took ${et}ms to finish.`); // Check if we have a tracker callback. if (timerData.cb) { From d5c71a827f6562bacee07ae49a71a785b79eb0a7 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 3 Mar 2021 16:32:49 -0300 Subject: [PATCH 08/58] updating UTs --- .../ga/__tests__/GaToSplit.spec.ts | 30 ++++---- .../ga/__tests__/SplitToGa.spec.ts | 4 +- src/listeners/__tests__/browser.spec.ts | 10 ++- src/listeners/__tests__/node.spec.ts | 13 ++-- src/logger/__tests__/index.spec.ts | 12 ++-- src/logger/__tests__/sdkLogger.mock.ts | 16 ++--- .../__tests__/sdkReadinessManager.spec.ts | 72 +++++++++---------- .../__tests__/sdkClientMethod.spec.ts | 5 +- .../__tests__/sdkClientMethodCS.spec.ts | 4 +- .../__tests__/index.asyncCache.spec.ts | 5 +- .../__tests__/index.syncCache.spec.ts | 3 +- .../__tests__/MySegmentsCacheInLocal.spec.ts | 3 +- .../__tests__/SplitsCacheInLocal.spec.ts | 25 +++---- .../__tests__/EventsCacheInRedis.spec.ts | 5 +- .../__tests__/ImpressionsCacheInRedis.spec.ts | 5 +- .../inRedis/__tests__/RedisAdapter.spec.ts | 58 +++++++-------- .../__tests__/SplitsCacheInRedis.spec.ts | 5 +- .../__tests__/splitChangesUpdater.spec.ts | 5 +- .../AuthClient/__tests__/index.spec.ts | 2 +- .../SSEHandler/__tests__/index.spec.ts | 11 +-- src/trackers/__tests__/eventTracker.spec.ts | 5 +- .../__tests__/impressionsTracker.spec.ts | 13 ++-- .../inputValidation/__tests__/apiKey.spec.ts | 46 ++++++------ .../__tests__/attributes.spec.ts | 22 +++--- .../inputValidation/__tests__/event.spec.ts | 22 +++--- .../__tests__/eventProperties.spec.ts | 56 +++++++-------- .../__tests__/eventValue.spec.ts | 28 ++++---- .../__tests__/isOperational.spec.ts | 30 ++++---- .../inputValidation/__tests__/key.spec.ts | 66 ++++++++--------- .../__tests__/preloadedData.spec.ts | 14 ++-- .../inputValidation/__tests__/split.spec.ts | 30 ++++---- .../__tests__/splitExistance.spec.ts | 34 ++++----- .../inputValidation/__tests__/splits.spec.ts | 32 ++++----- .../__tests__/trafficType.spec.ts | 26 +++---- .../__tests__/trafficTypeExistance.spec.ts | 44 ++++++------ .../__tests__/settings.mocks.ts | 17 +++-- .../__tests__/splitFilters.spec.ts | 50 ++++++------- .../__tests__/configurable.spec.ts | 23 +++--- .../integrations/__tests__/plugable.spec.ts | 20 +++--- .../settingsValidation/integrations/common.ts | 5 +- .../integrations/configurable.ts | 4 +- .../integrations/pluggable.ts | 4 +- .../storage/__tests__/storageCS.spec.ts | 11 +-- .../settingsValidation/storage/storageCS.ts | 5 +- 44 files changed, 459 insertions(+), 441 deletions(-) diff --git a/src/integrations/ga/__tests__/GaToSplit.spec.ts b/src/integrations/ga/__tests__/GaToSplit.spec.ts index 96f7c474..df416639 100644 --- a/src/integrations/ga/__tests__/GaToSplit.spec.ts +++ b/src/integrations/ga/__tests__/GaToSplit.spec.ts @@ -57,27 +57,27 @@ test('validateIdentities', () => { }); test('validateEventData', () => { - expect(() => { validateEventData(undefined); }).toThrow(); // throws exception if passed object is undefined - expect(() => { validateEventData(null); }).toThrow(); // throws exception if passed object is null + expect(() => { validateEventData(loggerMock, undefined); }).toThrow(); // throws exception if passed object is undefined + expect(() => { validateEventData(loggerMock, null); }).toThrow(); // throws exception if passed object is null - expect(validateEventData({})).toBe(false); // event must have a valid eventTypeId - expect(validateEventData({ eventTypeId: 'type' })).toBe(true); // event must have a valid eventTypeId - expect(validateEventData({ eventTypeId: 123 })).toBe(false); // event must have a valid eventTypeId + expect(validateEventData(loggerMock, {})).toBe(false); // event must have a valid eventTypeId + expect(validateEventData(loggerMock, { eventTypeId: 'type' })).toBe(true); // event must have a valid eventTypeId + expect(validateEventData(loggerMock, { eventTypeId: 123 })).toBe(false); // event must have a valid eventTypeId - expect(validateEventData({ eventTypeId: 'type', value: 'value' })).toBe(false); // event must have a valid value if present - expect(validateEventData({ eventTypeId: 'type', value: 0 })).toBe(true); // event must have a valid value if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', value: 'value' })).toBe(false); // event must have a valid value if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', value: 0 })).toBe(true); // event must have a valid value if present - expect(validateEventData({ eventTypeId: 'type', properties: ['prop1'] })).toBe(false); // event must have valid properties if present - expect(validateEventData({ eventTypeId: 'type', properties: { prop1: 'prop1' } })).toBe(true); // event must have valid properties if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', properties: ['prop1'] })).toBe(false); // event must have valid properties if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', properties: { prop1: 'prop1' } })).toBe(true); // event must have valid properties if present - expect(validateEventData({ eventTypeId: 'type', timestamp: true })).toBe(false); // event must have a valid timestamp if present - expect(validateEventData({ eventTypeId: 'type', timestamp: Date.now() })).toBe(true); // event must have a valid timestamp if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', timestamp: true })).toBe(false); // event must have a valid timestamp if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', timestamp: Date.now() })).toBe(true); // event must have a valid timestamp if present - expect(validateEventData({ eventTypeId: 'type', key: true })).toBe(false); // event must have a valid key if present - expect(validateEventData({ eventTypeId: 'type', key: 'key' })).toBe(true); // event must have a valid key if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', key: true })).toBe(false); // event must have a valid key if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', key: 'key' })).toBe(true); // event must have a valid key if present - expect(validateEventData({ eventTypeId: 'type', trafficTypeName: true })).toBe(false); // event must have a valid trafficTypeName if present - expect(validateEventData({ eventTypeId: 'type', trafficTypeName: 'tt' })).toBe(true); // event must have a valid trafficTypeName if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', trafficTypeName: true })).toBe(false); // event must have a valid trafficTypeName if present + expect(validateEventData(loggerMock, { eventTypeId: 'type', trafficTypeName: 'tt' })).toBe(true); // event must have a valid trafficTypeName if present }); test('fixEventTypeId', () => { diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index ae007941..1766bd4e 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -86,7 +86,7 @@ describe('SplitToGa', () => { let integration = new SplitToGa({}, loggerMock); expect(typeof integration).toBe('object'); - expect(loggerMock.w.mock.calls.length).toBe(0); + expect(loggerMock.warn.mock.calls.length).toBe(0); gaRemove(); expect(SplitToGa.getGa()).toBe(undefined); // should return undefined if ga command queue does not exist @@ -95,7 +95,7 @@ describe('SplitToGa', () => { expect(typeof integration).toBe('object'); // SplitToGa instances should be created even if ga command queue does not exist // @ts-expect-error integration.queue('fake-data'); - expect(loggerMock.w.mock.calls).toEqual([ // Warn when creating and queueing while ga command queue does not exist + expect(loggerMock.warn.mock.calls).toEqual([ // Warn when creating and queueing while ga command queue does not exist ['`ga` command queue not found. No hits will be sent until it is available.'], ['`ga` command queue not found. No hit was sent.'] ]); diff --git a/src/listeners/__tests__/browser.spec.ts b/src/listeners/__tests__/browser.spec.ts index d1be1968..cc428917 100644 --- a/src/listeners/__tests__/browser.spec.ts +++ b/src/listeners/__tests__/browser.spec.ts @@ -1,7 +1,7 @@ import BrowserSignalListener from '../browser'; import { IEventsCacheSync, IImpressionCountsCacheSync, IImpressionsCacheSync, IStorageSync } from '../../storages/types'; import { ISplitApi } from '../../services/types'; -import { settingsSplitApi } from '../../utils/settingsValidation/__tests__/settings.mocks'; +import { fullSettings } from '../../utils/settingsValidation/__tests__/settings.mocks'; /* Mocks start */ @@ -62,8 +62,6 @@ const fakeSplitApi = { postTestImpressionsCount: jest.fn(() => Promise.resolve()) } as ISplitApi; -const fakeSettings = settingsSplitApi; - const UNLOAD_DOM_EVENT = 'unload'; const unloadEventListeners = new Set<() => any>(); @@ -109,7 +107,7 @@ function triggerUnloadEvent() { test('Browser JS listener / Impressions optimized mode', (done) => { - const listener = new BrowserSignalListener(undefined, fakeSettings, fakeStorageOptimized as IStorageSync, fakeSplitApi); + const listener = new BrowserSignalListener(undefined, fullSettings, fakeStorageOptimized as IStorageSync, fakeSplitApi); listener.start(); @@ -140,7 +138,7 @@ test('Browser JS listener / Impressions optimized mode', (done) => { test('Browser JS listener / Impressions debug mode', (done) => { - const listener = new BrowserSignalListener(undefined, fakeSettings, fakeStorageDebug as IStorageSync, fakeSplitApi); + const listener = new BrowserSignalListener(undefined, fullSettings, fakeStorageDebug as IStorageSync, fakeSplitApi); listener.start(); @@ -174,7 +172,7 @@ test('Browser JS listener / Impressions debug mode without sendBeacon API', (don const sendBeacon = global.navigator.sendBeacon; // @ts-expect-error global.navigator.sendBeacon = undefined; - const listener = new BrowserSignalListener(undefined, fakeSettings, fakeStorageDebug as IStorageSync, fakeSplitApi); + const listener = new BrowserSignalListener(undefined, fullSettings, fakeStorageDebug as IStorageSync, fakeSplitApi); listener.start(); diff --git a/src/listeners/__tests__/node.spec.ts b/src/listeners/__tests__/node.spec.ts index 57deeea4..cc16aff4 100644 --- a/src/listeners/__tests__/node.spec.ts +++ b/src/listeners/__tests__/node.spec.ts @@ -1,6 +1,5 @@ import NodeSignalListener from '../node'; -import { settingsSplitApi } from '../../utils/settingsValidation/__tests__/settings.mocks'; -const fakeSettings = settingsSplitApi; +import { fullSettings } from '../../utils/settingsValidation/__tests__/settings.mocks'; const processOnSpy = jest.spyOn(process, 'on'); const processRemoveListenerSpy = jest.spyOn(process, 'removeListener'); @@ -9,7 +8,7 @@ const processKillSpy = jest.spyOn(process, 'kill').mockImplementation(() => true test('Node JS listener / Signal Listener class methods and start/stop functionality', () => { const handlerMock = jest.fn(); - const listener = new NodeSignalListener(handlerMock, fakeSettings); + const listener = new NodeSignalListener(handlerMock, fullSettings); listener.start(); @@ -29,7 +28,7 @@ test('Node JS listener / Signal Listener class methods and start/stop functional test('Node JS listener / Signal Listener SIGTERM callback with sync handler', () => { const handlerMock = jest.fn(); - const listener = new NodeSignalListener(handlerMock, fakeSettings); + const listener = new NodeSignalListener(handlerMock, fullSettings); listener.start(); // Stub stop function since we don't want side effects on test. @@ -58,7 +57,7 @@ test('Node JS listener / Signal Listener SIGTERM callback with sync handler', () test('Node JS listener / Signal Listener SIGTERM callback with sync handler that throws an error', () => { const handlerMock = jest.fn(() => { throw 'some error'; }); - const listener = new NodeSignalListener(handlerMock, fakeSettings); + const listener = new NodeSignalListener(handlerMock, fullSettings); listener.start(); // Stub stop function since we don't want side effects on test. @@ -95,7 +94,7 @@ test('Node JS listener / Signal Listener SIGTERM callback with async handler', a }); const handlerMock = jest.fn(() => fakePromise); - const listener = new NodeSignalListener(handlerMock, fakeSettings); + const listener = new NodeSignalListener(handlerMock, fullSettings); // Stub stop function since we don't want side effects on test. jest.spyOn(listener, 'stop'); @@ -139,7 +138,7 @@ test('Node JS listener / Signal Listener SIGTERM callback with async handler tha }); const handlerMock = jest.fn(() => fakePromise); - const listener = new NodeSignalListener(handlerMock, fakeSettings); + const listener = new NodeSignalListener(handlerMock, fullSettings); // Stub stop function since we don't want side effects on test. jest.spyOn(listener, 'stop'); diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index cc01c897..c993df23 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -34,10 +34,10 @@ test('SPLIT LOGGER / Logger class shape', () => { const logger = new Logger('test-category', {}); - expect(typeof logger.d).toBe('function'); // instance.d should be a method. - expect(typeof logger.i).toBe('function'); // instance.i should be a method. - expect(typeof logger.w).toBe('function'); // instance.w should be a method. - expect(typeof logger.e).toBe('function'); // instance.e should be a method. + expect(typeof logger.debug).toBe('function'); // instance.d should be a method. + expect(typeof logger.info).toBe('function'); // instance.i should be a method. + expect(typeof logger.warn).toBe('function'); // instance.w should be a method. + expect(typeof logger.error).toBe('function'); // instance.e should be a method. }); @@ -60,7 +60,7 @@ function testLogLevels(levelToTest: string) { const runTests = (showLevel?: boolean, displayAllErrors?: boolean) => { let logLevelLogsCounter = 0; let testForNoLog = false; - const logMethod = levelToTest.toLowerCase().charAt(0); + const logMethod = levelToTest.toLowerCase(); const logCategory = `test-category-${logMethod}${displayAllErrors ? 'displayAllErrors' : ''}`; const instance = new Logger(logCategory, { showLevel, displayAllErrors @@ -71,7 +71,7 @@ function testLogLevels(levelToTest: string) { const expectedMessage = buildExpectedMessage(levelToTest, logCategory, logMsg, showLevel); // Log error should always be visible. - if (logMethod === LOG_LEVELS.ERROR.toLowerCase().charAt(0) && displayAllErrors) testForNoLog = false; + if (logMethod === LOG_LEVELS.ERROR.toLowerCase() && displayAllErrors) testForNoLog = false; // Set the logLevel for this iteration. setLogLevel(LogLevels[logLevel]); diff --git a/src/logger/__tests__/sdkLogger.mock.ts b/src/logger/__tests__/sdkLogger.mock.ts index e8eff067..0ba6aa71 100644 --- a/src/logger/__tests__/sdkLogger.mock.ts +++ b/src/logger/__tests__/sdkLogger.mock.ts @@ -7,17 +7,17 @@ jest.mock('../sdkLogger'); import { logFactory } from '../sdkLogger'; export const loggerMock = { - w: jest.fn(), - e: jest.fn(), - d: jest.fn(), - i: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + debug: jest.fn(), + info: jest.fn(), }; (logFactory as jest.Mock).mockReturnValue(loggerMock); export function mockClear() { - loggerMock.w.mockClear(); - loggerMock.e.mockClear(); - loggerMock.d.mockClear(); - loggerMock.i.mockClear(); + loggerMock.warn.mockClear(); + loggerMock.error.mockClear(); + loggerMock.debug.mockClear(); + loggerMock.info.mockClear(); } diff --git a/src/readiness/__tests__/sdkReadinessManager.spec.ts b/src/readiness/__tests__/sdkReadinessManager.spec.ts index 3d6b1d6f..d1f0f140 100644 --- a/src/readiness/__tests__/sdkReadinessManager.spec.ts +++ b/src/readiness/__tests__/sdkReadinessManager.spec.ts @@ -41,7 +41,7 @@ describe('SDK Readiness Manager - Event emitter', () => { test('Providing the gate object to get the SDK status interface that manages events', () => { expect(typeof sdkReadinessManagerFactory).toBe('function'); // The module exposes a function. - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); expect(typeof sdkReadinessManager).toBe('object'); // The function result contains the readiness manager and a sdkStatus object. const gateMock = sdkReadinessManager.readinessManager.gate; const sdkStatus = sdkReadinessManager.sdkStatus; @@ -77,55 +77,55 @@ describe('SDK Readiness Manager - Event emitter', () => { }); test('The event callbacks should work as expected - SDK_READY_FROM_CACHE', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); const gateMock = sdkReadinessManager.readinessManager.gate; const readyFromCacheEventCB = gateMock.once.mock.calls[2][1]; readyFromCacheEventCB(); - expect(loggerMock.i.mock.calls.length).toBe(1); // If the SDK_READY_FROM_CACHE event fires, we get a info message. - expect(loggerMock.i.mock.calls[0]).toEqual(['Split SDK is ready from cache.']); // Telling us the SDK is ready to be used with data from cache. + expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY_FROM_CACHE event fires, we get a info message. + expect(loggerMock.info.mock.calls[0]).toEqual(['Split SDK is ready from cache.']); // Telling us the SDK is ready to be used with data from cache. }); test('The event callbacks should work as expected - SDK_READY emits with no callbacks', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); // Get the callbacks const addListenerCB = sdkReadinessManager.readinessManager.gate.on.mock.calls[1][1]; emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.w.mock.calls.length).toBe(1); // If the SDK_READY event fires and we have no callbacks for it (neither event nor ready promise) we get a warning. - expect(loggerMock.w.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // Telling us there were no listeners and evaluations before this point may have been incorrect. + expect(loggerMock.warn.mock.calls.length).toBe(1); // If the SDK_READY event fires and we have no callbacks for it (neither event nor ready promise) we get a warning. + expect(loggerMock.warn.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // Telling us there were no listeners and evaluations before this point may have been incorrect. // Now it's marked as ready. addListenerCB('this event we do not care'); - expect(loggerMock.e.mock.calls.length).toBe(0); // Now if we add a listener to an event unrelated with readiness, we get no errors logged. + expect(loggerMock.error.mock.calls.length).toBe(0); // Now if we add a listener to an event unrelated with readiness, we get no errors logged. addListenerCB(SDK_READY); - expect(loggerMock.e.mock.calls).toEqual([['A listener was added for SDK_READY on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY we get the corresponding warning. + expect(loggerMock.error.mock.calls).toEqual([['A listener was added for SDK_READY on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY we get the corresponding warning. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); addListenerCB(SDK_READY_TIMED_OUT); - expect(loggerMock.e.mock.calls).toEqual([['A listener was added for SDK_READY_TIMED_OUT on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY_TIMED_OUT we get the corresponding warning. + expect(loggerMock.error.mock.calls).toEqual([['A listener was added for SDK_READY_TIMED_OUT on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY_TIMED_OUT we get the corresponding warning. }); test('The event callbacks should work as expected - SDK_READY emits with callbacks', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); // Get the callbacks const addListenerCB = sdkReadinessManager.readinessManager.gate.on.mock.calls[1][1]; addListenerCB(SDK_READY); - expect(loggerMock.w.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no warnings are logged. - expect(loggerMock.e.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no errors are logged. + expect(loggerMock.warn.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no warnings are logged. + expect(loggerMock.error.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no errors are logged. emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.w.mock.calls.length).toBe(0); // As we had at least one listener, we get no warnings. - expect(loggerMock.e.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // As we had at least one listener, we get no warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); const gateMock = sdkReadinessManager.readinessManager.gate; // Get the callbacks @@ -141,11 +141,11 @@ describe('SDK Readiness Manager - Event emitter', () => { removeListenerCB(SDK_READY); emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.w.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // We get the warning. + expect(loggerMock.warn.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // We get the warning. }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); const gateMock = sdkReadinessManager.readinessManager.gate; // Get the callbacks @@ -162,12 +162,12 @@ describe('SDK Readiness Manager - Event emitter', () => { removeListenerCB('random event'); emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.w.mock.calls.length).toBe(0); // No warning when the SDK is ready as we still have one listener. + expect(loggerMock.warn.mock.calls.length).toBe(0); // No warning when the SDK is ready as we still have one listener. }); test('The event callbacks should work as expected - SDK_READY emits with expected internal callbacks', () => { // the sdkReadinessManager expects more than one SDK_READY callback to not log the "No listeners" warning - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, undefined /* default readyTimeout */, 1 /* internalReadyCbCount */); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock, undefined /* default readyTimeout */, 1 /* internalReadyCbCount */); const gateMock = sdkReadinessManager.readinessManager.gate; // Get the callbacks @@ -179,19 +179,19 @@ describe('SDK Readiness Manager - Event emitter', () => { addListenerCB(SDK_READY); removeListenerCB(SDK_READY); - expect(loggerMock.w.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no warnings are logged. - expect(loggerMock.e.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no errors are logged. + expect(loggerMock.warn.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no warnings are logged. + expect(loggerMock.error.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no errors are logged. emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.w.mock.calls.length).not.toBe(0); // As we had the same amount of listeners that the expected, we get a warning. - expect(loggerMock.e.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. + expect(loggerMock.warn.mock.calls.length).not.toBe(0); // As we had the same amount of listeners that the expected, we get a warning. + expect(loggerMock.error.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. }); }); describe('SDK Readiness Manager - Ready promise', () => { test('.ready() promise behaviour for clients', async (done) => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); const ready = sdkReadinessManager.sdkStatus.ready(); expect(ready instanceof Promise).toBe(true); // It should return a promise. @@ -220,7 +220,7 @@ describe('SDK Readiness Manager - Ready promise', () => { // control assertion. stubs already reset. expect(testPassedCount).toBe(2); - const sdkReadinessManagerForTimedout = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManagerForTimedout = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); const readyForTimeout = sdkReadinessManagerForTimedout.sdkStatus.ready(); @@ -260,15 +260,15 @@ describe('SDK Readiness Manager - Ready promise', () => { }); test('Full blown ready promise count as a callback and resolves on SDK_READY', (done) => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); const readyPromise = sdkReadinessManager.sdkStatus.ready(); // Get the callback const readyEventCB = sdkReadinessManager.readinessManager.gate.once.mock.calls[0][1]; readyEventCB(); - expect(loggerMock.w.mock.calls).toEqual([['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']]); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise. - loggerMock.w.mockClear(); + expect(loggerMock.warn.mock.calls).toEqual([['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']]); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise. + loggerMock.warn.mockClear(); readyPromise.then(() => { expect('The ready promise is resolved when the gate emits SDK_READY.'); @@ -278,11 +278,11 @@ describe('SDK Readiness Manager - Ready promise', () => { }); readyEventCB(); - expect(loggerMock.w.mock.calls.length).toBe(0); // But if we have a listener there are no warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // But if we have a listener there are no warnings. }); test('.ready() rejected promises have a default onRejected handler that just logs the error', (done) => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock); + const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); let readyForTimeout = sdkReadinessManager.sdkStatus.ready(); emitTimeoutEvent(sdkReadinessManager.readinessManager); // make the SDK "timed out" @@ -291,14 +291,14 @@ describe('SDK Readiness Manager - Ready promise', () => { () => { throw new Error('It should be a promise that was rejected on SDK_READY_TIMED_OUT, not resolved.'); } ); - expect(loggerMock.e.mock.calls.length === 0).toBe(true); // not called until promise is rejected + expect(loggerMock.error.mock.calls.length === 0).toBe(true); // not called until promise is rejected setTimeout(() => { - expect(loggerMock.e.mock.calls).toEqual([[timeoutErrorMessage]]); // If we don\'t handle the rejected promise, an error is logged. + expect(loggerMock.error.mock.calls).toEqual([[timeoutErrorMessage]]); // If we don\'t handle the rejected promise, an error is logged. readyForTimeout = sdkReadinessManager.sdkStatus.ready(); setTimeout(() => { - expect(loggerMock.e).lastCalledWith('Split SDK has emitted SDK_READY_TIMED_OUT event.'); // If we don\'t handle a new .ready() rejected promise, an error is logged. + expect(loggerMock.error).lastCalledWith('Split SDK has emitted SDK_READY_TIMED_OUT event.'); // If we don\'t handle a new .ready() rejected promise, an error is logged. readyForTimeout = sdkReadinessManager.sdkStatus.ready(); readyForTimeout @@ -306,7 +306,7 @@ describe('SDK Readiness Manager - Ready promise', () => { .then(() => { throw new Error(); }) .catch((error) => { expect(error).toBe('Split SDK has emitted SDK_READY_TIMED_OUT event.'); - expect(loggerMock.e).toBeCalledTimes(2); // If we provide an onRejected handler, even chaining several onFulfilled handlers, the error is not logged. + expect(loggerMock.error).toBeCalledTimes(2); // If we provide an onRejected handler, even chaining several onFulfilled handlers, the error is not logged. done(); }); }, 0); diff --git a/src/sdkClient/__tests__/sdkClientMethod.spec.ts b/src/sdkClient/__tests__/sdkClientMethod.spec.ts index 908070de..278ec615 100644 --- a/src/sdkClient/__tests__/sdkClientMethod.spec.ts +++ b/src/sdkClient/__tests__/sdkClientMethod.spec.ts @@ -1,3 +1,4 @@ +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; import { CONSUMER_MODE, STANDALONE_MODE } from '../../utils/constants'; import { sdkClientMethodFactory } from '../sdkClientMethod'; import { assertClientApi } from './testUtils'; @@ -11,7 +12,7 @@ const paramMocks = [ syncManager: undefined, sdkReadinessManager: { sdkStatus: jest.fn(), readinessManager: { destroy: jest.fn() } }, signalListener: undefined, - settings: { mode: CONSUMER_MODE } + settings: { mode: CONSUMER_MODE, log: loggerMock } }, // SyncManager (i.e., Sync SDK) and Signal listener { @@ -19,7 +20,7 @@ const paramMocks = [ syncManager: { stop: jest.fn(), flush: jest.fn(() => Promise.resolve()) }, sdkReadinessManager: { sdkStatus: jest.fn(), readinessManager: { destroy: jest.fn() } }, signalListener: { stop: jest.fn() }, - settings: { mode: STANDALONE_MODE } + settings: { mode: STANDALONE_MODE, log: loggerMock } } ]; diff --git a/src/sdkClient/__tests__/sdkClientMethodCS.spec.ts b/src/sdkClient/__tests__/sdkClientMethodCS.spec.ts index ba066267..345909f9 100644 --- a/src/sdkClient/__tests__/sdkClientMethodCS.spec.ts +++ b/src/sdkClient/__tests__/sdkClientMethodCS.spec.ts @@ -210,12 +210,10 @@ describe('sdkClientMethodCSFactory', () => { const paramsWithInvalidKeyAndTT = { ...params, settings: { + ...params.settings, core: { key: true, // invalid key trafficType: '' // invalid TT - }, - startup: { - readyTimeout: 1, } } }; diff --git a/src/sdkManager/__tests__/index.asyncCache.spec.ts b/src/sdkManager/__tests__/index.asyncCache.spec.ts index 993704d5..0694f04f 100644 --- a/src/sdkManager/__tests__/index.asyncCache.spec.ts +++ b/src/sdkManager/__tests__/index.asyncCache.spec.ts @@ -5,6 +5,7 @@ import { sdkManagerFactory } from '../index'; import SplitsCacheInRedis from '../../storages/inRedis/SplitsCacheInRedis'; import KeyBuilderSS from '../../storages/KeyBuilderSS'; import { ISdkReadinessManager } from '../../readiness/types'; +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; // @ts-expect-error const sdkReadinessManagerMock = { @@ -20,8 +21,8 @@ test('MANAGER API / Async cache (In Redis)', async () => { /** Setup: create manager */ const connection = new Redis({}); // @ts-expect-error const keys = new KeyBuilderSS(); - const cache = new SplitsCacheInRedis(keys, connection); - const manager = sdkManagerFactory(cache, sdkReadinessManagerMock); + const cache = new SplitsCacheInRedis(loggerMock, keys, connection); + const manager = sdkManagerFactory(cache, sdkReadinessManagerMock, loggerMock); await cache.clear(); await cache.addSplit(splitObject.name, JSON.stringify(splitObject)); diff --git a/src/sdkManager/__tests__/index.syncCache.spec.ts b/src/sdkManager/__tests__/index.syncCache.spec.ts index 85440d58..8880b90a 100644 --- a/src/sdkManager/__tests__/index.syncCache.spec.ts +++ b/src/sdkManager/__tests__/index.syncCache.spec.ts @@ -3,6 +3,7 @@ import splitView from './mocks/output.json'; import { sdkManagerFactory } from '../index'; import SplitsCacheInMemory from '../../storages/inMemory/SplitsCacheInMemory'; import { ISdkReadinessManager } from '../../readiness/types'; +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; // @ts-expect-error const sdkReadinessManagerMock = { @@ -17,7 +18,7 @@ describe('MANAGER API / Sync cache (In Memory)', () => { /** Setup: create manager */ const cache = new SplitsCacheInMemory(); - const manager = sdkManagerFactory(cache, sdkReadinessManagerMock); + const manager = sdkManagerFactory(cache, sdkReadinessManagerMock, loggerMock); cache.addSplit(splitObject.name, JSON.stringify(splitObject)); test('List all splits', () => { diff --git a/src/storages/inLocalStorage/__tests__/MySegmentsCacheInLocal.spec.ts b/src/storages/inLocalStorage/__tests__/MySegmentsCacheInLocal.spec.ts index 7040e797..158f8c2c 100644 --- a/src/storages/inLocalStorage/__tests__/MySegmentsCacheInLocal.spec.ts +++ b/src/storages/inLocalStorage/__tests__/MySegmentsCacheInLocal.spec.ts @@ -1,9 +1,10 @@ import MySegmentsCacheInLocal from '../MySegmentsCacheInLocal'; import KeyBuilderCS from '../../KeyBuilderCS'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('SEGMENT CACHE / in LocalStorage', () => { const keys = new KeyBuilderCS('SPLITIO', 'user'); - const cache = new MySegmentsCacheInLocal(keys); + const cache = new MySegmentsCacheInLocal(loggerMock, keys); cache.clear(); diff --git a/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts b/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts index 48a4e53f..b8105afd 100644 --- a/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts +++ b/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts @@ -1,8 +1,9 @@ import SplitsCacheInLocal from '../SplitsCacheInLocal'; import KeyBuilderCS from '../../KeyBuilderCS'; +import { noopLogger } from '../../../logger/noopLogger'; test('SPLIT CACHE / LocalStorage', () => { - const cache = new SplitsCacheInLocal(new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); cache.clear(); @@ -43,7 +44,7 @@ test('SPLIT CACHE / LocalStorage', () => { }); test('SPLIT CACHE / LocalStorage / Get Keys', () => { - const cache = new SplitsCacheInLocal(new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); cache.addSplit('lol1', 'something'); cache.addSplit('lol2', 'something else'); @@ -55,7 +56,7 @@ test('SPLIT CACHE / LocalStorage / Get Keys', () => { }); test('SPLIT CACHE / LocalStorage / Add Splits', () => { - const cache = new SplitsCacheInLocal(new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); cache.addSplits([ ['lol1', 'something'], @@ -69,7 +70,7 @@ test('SPLIT CACHE / LocalStorage / Add Splits', () => { }); test('SPLIT CACHE / LocalStorage / trafficTypeExists and ttcache tests', () => { - const cache = new SplitsCacheInLocal(new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); cache.addSplits([ // loop of addSplit ['split1', '{ "trafficTypeName": "user_tt" }'], @@ -108,7 +109,7 @@ test('SPLIT CACHE / LocalStorage / trafficTypeExists and ttcache tests', () => { }); test('SPLIT CACHE / LocalStorage / killLocally', () => { - const cache = new SplitsCacheInLocal(new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); cache.addSplit('lol1', '{ "name": "something"}'); cache.addSplit('lol2', '{ "name": "something else"}'); const initialChangeNumber = cache.getChangeNumber(); @@ -117,24 +118,24 @@ test('SPLIT CACHE / LocalStorage / killLocally', () => { let updated = cache.killLocally('nonexistent_split', 'other_treatment', 101); const nonexistentSplit = cache.getSplit('nonexistent_split'); - expect(updated).toBe( false); // t exist + expect(updated).toBe(false); // t exist expect(nonexistentSplit).toBe(null); // non-existent split keeps being non-existent // kill an existent split updated = cache.killLocally('lol1', 'some_treatment', 100); let lol1Split = JSON.parse(cache.getSplit('lol1') as string); - expect(updated).toBe( true); // killLocally resolves with update if split is changed + expect(updated).toBe(true); // killLocally resolves with update if split is changed expect(lol1Split.killed).toBe(true); // existing split must be killed - expect(lol1Split.defaultTreatment).toBe( 'some_treatment'); // existing split must have new default treatment - expect(lol1Split.changeNumber).toBe( 100); // existing split must have the given change number - expect(cache.getChangeNumber()).toBe( initialChangeNumber); // cache changeNumber is not changed + expect(lol1Split.defaultTreatment).toBe('some_treatment'); // existing split must have new default treatment + expect(lol1Split.changeNumber).toBe(100); // existing split must have the given change number + expect(cache.getChangeNumber()).toBe(initialChangeNumber); // cache changeNumber is not changed // not update if changeNumber is old updated = cache.killLocally('lol1', 'some_treatment_2', 90); lol1Split = JSON.parse(cache.getSplit('lol1') as string); - expect(updated).toBe( false); // killLocally resolves without update if changeNumber is old - expect(lol1Split.defaultTreatment).not.toBe( 'some_treatment_2'); // existing split is not updated if given changeNumber is older + expect(updated).toBe(false); // killLocally resolves without update if changeNumber is old + expect(lol1Split.defaultTreatment).not.toBe('some_treatment_2'); // existing split is not updated if given changeNumber is older }); diff --git a/src/storages/inRedis/__tests__/EventsCacheInRedis.spec.ts b/src/storages/inRedis/__tests__/EventsCacheInRedis.spec.ts index 6b146041..c4384726 100644 --- a/src/storages/inRedis/__tests__/EventsCacheInRedis.spec.ts +++ b/src/storages/inRedis/__tests__/EventsCacheInRedis.spec.ts @@ -1,6 +1,7 @@ import Redis from 'ioredis'; import find from 'lodash/find'; import isEqual from 'lodash/isEqual'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import KeyBuilderSS from '../../KeyBuilderSS'; import EventsCacheInRedis from '../EventsCacheInRedis'; import { metadataBuilder } from '../index'; @@ -26,11 +27,11 @@ test('EVENTS CACHE IN REDIS / should incrementally store values in redis', async expect(redisValues.length).toBe(0); // control assertion, there are no events previously queued. - const cache = new EventsCacheInRedis(keys, connection, fakeRedisMetadata); + const cache = new EventsCacheInRedis(loggerMock, keys, connection, fakeRedisMetadata); // I'll use a "bad" instance so I can force an issue with the rpush command. I'll store an integer and will make the cache try to use rpush there. await connection.set('non-list-key', 10); // @ts-expect-error - const faultyCache = new EventsCacheInRedis({ + const faultyCache = new EventsCacheInRedis(loggerMock, { buildEventsKey: () => 'non-list-key' }, connection, fakeRedisMetadata); diff --git a/src/storages/inRedis/__tests__/ImpressionsCacheInRedis.spec.ts b/src/storages/inRedis/__tests__/ImpressionsCacheInRedis.spec.ts index 93dcb55c..70e4724a 100644 --- a/src/storages/inRedis/__tests__/ImpressionsCacheInRedis.spec.ts +++ b/src/storages/inRedis/__tests__/ImpressionsCacheInRedis.spec.ts @@ -2,12 +2,13 @@ import Redis from '../RedisAdapter'; import KeyBuilderSS from '../../KeyBuilderSS'; import ImpressionsCacheInRedis from '../ImpressionsCacheInRedis'; import IORedis, { BooleanResponse } from 'ioredis'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('IMPRESSIONS CACHE IN REDIS / should incrementally store values', async () => { const prefix = 'impr_cache_ut'; const impressionsKey = `${prefix}.impressions`; const testMeta = { thisIsTheMeta: true }; - const connection = new Redis({}); + const connection = new Redis(loggerMock, {}); // @ts-expect-error const keys = new KeyBuilderSS(prefix); // @ts-expect-error const c = new ImpressionsCacheInRedis(keys, connection, testMeta); @@ -67,7 +68,7 @@ test('IMPRESSIONS CACHE IN REDIS / should not resolve track before calling expir const prefix = 'impr_cache_ut_2'; const impressionsKey = `${prefix}.impressions`; const testMeta = { thisIsTheMeta: true }; - const connection = new Redis({}); + const connection = new Redis(loggerMock, {}); // @ts-expect-error const keys = new KeyBuilderSS(prefix); // @ts-expect-error const c = new ImpressionsCacheInRedis(keys, connection, testMeta); diff --git a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts index 448191c2..4fd3e599 100644 --- a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts +++ b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts @@ -65,7 +65,7 @@ function clearAllMocks() { test('STORAGE Redis Adapter / Class', () => { expect(Object.getPrototypeOf(RedisAdapter)).toBe(ioredis); // The returned class extends from the library of choice (ioredis). - const instance = new RedisAdapter({ + const instance = new RedisAdapter(loggerMock, { url: 'redis://localhost:6379/0', connectionTimeout: 10000, operationTimeout: 10000 @@ -85,7 +85,7 @@ test('STORAGE Redis Adapter / ioredis constructor params and static method _defi host: 'fake_host', port: '6355', 'db': 5, pass: 'fake_pass' }; - new RedisAdapter({ + new RedisAdapter(loggerMock, { url: redisUrl, connectionTimeout: 123, operationTimeout: 124 @@ -95,7 +95,7 @@ test('STORAGE Redis Adapter / ioredis constructor params and static method _defi expect(constructorParams[0]).toBe(redisUrl); // When we use the Redis URL, that should be the first parameter passed to ioredis constructor expect(constructorParams[1]).toEqual({ enableOfflineQueue: false, connectTimeout: 10000, lazyConnect: false }); // and the second parameter would be the default settings for the lib. - new RedisAdapter({ + new RedisAdapter(loggerMock, { ...redisParams, connectionTimeout: 123, operationTimeout: 124 @@ -105,7 +105,7 @@ test('STORAGE Redis Adapter / ioredis constructor params and static method _defi // we keep "pass" instead of "password" on our settings API to be backwards compatible. expect(constructorParams[0]).toEqual({ host: redisParams.host, port: redisParams.port, db: redisParams.db, password: redisParams.pass, enableOfflineQueue: false, connectTimeout: 10000, lazyConnect: false }); // If we send all the redis params separate, it will pass one object to the library containing that and the rest of the options. - new RedisAdapter({ + new RedisAdapter(loggerMock, { ...redisParams, url: redisUrl, connectionTimeout: 123, @@ -157,7 +157,7 @@ test('STORAGE Redis Adapter / instance methods - _listenToEvents', (done) => { expect(ioredisMock.once.mock.calls.length).toBe(0); // Control assertion expect(ioredisMock[METHODS_TO_PROMISE_WRAP[0]].mock.calls.length).toBe(0); // Control assertion - const instance = new RedisAdapter({ + const instance = new RedisAdapter(loggerMock, { url: 'redis://localhost:6379/0' }); @@ -182,21 +182,21 @@ test('STORAGE Redis Adapter / instance methods - _listenToEvents', (done) => { expect(secondCallArgs[0]).toBe('close'); // First argument for the first call should be the "close" event. expect(typeof secondCallArgs[1]).toBe('function'); // second argument for the first call should be a callback function. - expect(loggerMock.w.mock.calls.length).toBe(0); // Control assertion + expect(loggerMock.warn.mock.calls.length).toBe(0); // Control assertion secondCallArgs[1](); // Execute the callback for "close" - expect(loggerMock.i.mock.calls.length).toBe(1); // The callback for the "close" event will only log info to the user about what is going on. - expect(loggerMock.i.mock.calls[0]).toEqual(['Redis connection closed.']); // The callback for the "close" event will only log info to the user about what is going on. + expect(loggerMock.info.mock.calls.length).toBe(1); // The callback for the "close" event will only log info to the user about what is going on. + expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection closed.']); // The callback for the "close" event will only log info to the user about what is going on. - loggerMock.i.mockClear(); - expect(loggerMock.i.mock.calls.length).toBe(0); // Control assertion + loggerMock.info.mockClear(); + expect(loggerMock.info.mock.calls.length).toBe(0); // Control assertion expect(Array.isArray(instance._notReadyCommandsQueue)).toBe(true); // Control assertion // Without any offline commands queued, execute the callback for "ready" firstCallArgs[1](); - expect(loggerMock.i.mock.calls.length).not.toBe(0); // The callback for the "ready" event will inform the user about the trigger. - expect(loggerMock.i.mock.calls[0]).toEqual(['Redis connection established. Queued commands: 0.']); // The callback for the "ready" event will inform the user about the trigger. + expect(loggerMock.info.mock.calls.length).not.toBe(0); // The callback for the "ready" event will inform the user about the trigger. + expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection established. Queued commands: 0.']); // The callback for the "ready" event will inform the user about the trigger. expect(instance._notReadyCommandsQueue).toBe(undefined); // After the DB is ready, it will clean up the offline commands queue so we do not queue commands anymore. // Don't do this at home @@ -213,13 +213,13 @@ test('STORAGE Redis Adapter / instance methods - _listenToEvents', (done) => { reject: jest.fn() }; instance._notReadyCommandsQueue = [queuedGetCommand, queuedSetCommand]; - loggerMock.i.mockClear(); + loggerMock.info.mockClear(); // execute the callback for "ready" once more firstCallArgs[1](); - expect(loggerMock.i.mock.calls.length).toBe(3); // If we had queued commands, it will log the event (1 call) as well as each executed command (n calls). - expect(loggerMock.i.mock.calls).toEqual([ + expect(loggerMock.info.mock.calls.length).toBe(3); // If we had queued commands, it will log the event (1 call) as well as each executed command (n calls). + expect(loggerMock.info.mock.calls).toEqual([ ['Redis connection established. Queued commands: 2.'], // The callback for the "ready" event will inform the user about the trigger and the amount of queued commands. ['Executing queued GET command.'], // If we had queued, it will log the event as well as each executed command. ['Executing queued SET command.'] // If we had queued commands, it will log the event as well as each executed command. @@ -239,7 +239,7 @@ test('STORAGE Redis Adapter / instance methods - _listenToEvents', (done) => { test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queueing commands 1/2 - Error path', (done) => { clearAllMocks(); - const instance = new RedisAdapter({ + const instance = new RedisAdapter(loggerMock, { url: 'redis://localhost:6379/0' }); @@ -263,7 +263,7 @@ test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queuein }); instance._notReadyCommandsQueue = false; // Remove the queue. - loggerMock.e.resetHistory; + loggerMock.error.resetHistory; forEach(METHODS_TO_PROMISE_WRAP, (methodName, index) => { // We do NOT have the commands queue on this state, so a call for this methods will execute the command. @@ -286,7 +286,7 @@ test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queuein commandTimeoutResolver.rej('test'); setTimeout(() => { // Allow the promises to tick. expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes with error, it's promise is removed from the instance._runningCommands queue. - expect(loggerMock.e.mock.calls[index]).toEqual([`${methodName} operation threw an error or exceeded configured timeout of 5000ms. Message: test`]); // The log error method should be called with the corresponding messages, depending on the method, error and operationTimeout. + expect(loggerMock.error.mock.calls[index]).toEqual([`${methodName} operation threw an error or exceeded configured timeout of 5000ms. Message: test`]); // The log error method should be called with the corresponding messages, depending on the method, error and operationTimeout. }, 0); }); @@ -298,7 +298,7 @@ test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queuein test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queueing commands 2/2 - Success path', (done) => { clearAllMocks(); - const instance = new RedisAdapter({ + const instance = new RedisAdapter(loggerMock, { url: 'redis://localhost:6379/0' }); @@ -312,7 +312,7 @@ test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queuein commandTimeoutResolver.res('test'); setTimeout(() => { // Allow the promises to tick. - expect(loggerMock.e.mock.calls.length).toBe(0); // No error should be logged + expect(loggerMock.error.mock.calls.length).toBe(0); // No error should be logged expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes successfully, it's promise is removed from the instance._runningCommands queue. }, 0); }); @@ -325,7 +325,7 @@ test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queuein test('STORAGE Redis Adapter / instance methods - _setDisconnectWrapper', (done) => { clearAllMocks(); - const instance = new RedisAdapter({ + const instance = new RedisAdapter(loggerMock, { url: 'redis://localhost:6379/0' }); @@ -337,9 +337,9 @@ test('STORAGE Redis Adapter / instance methods - _setDisconnectWrapper', (done) expect(ioredisMock.disconnect.mock.calls.length).toBe(0); // Original method should not be called right away. setTimeout(() => { // o queued commands timeout wrapper. - expect(loggerMock.d.mock.calls).toEqual([['No commands pending execution, disconnect.']]); + expect(loggerMock.debug.mock.calls).toEqual([['No commands pending execution, disconnect.']]); expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously - loggerMock.d.mockClear(); + loggerMock.debug.mockClear(); ioredisMock.disconnect.mockClear(); // Second run, two pending commands, one will fail. @@ -350,15 +350,15 @@ test('STORAGE Redis Adapter / instance methods - _setDisconnectWrapper', (done) rejectedPromise.catch(() => { }); // Swallow the unhandled to avoid unhandledRejection warns setTimeout(() => { // queued with rejection timeout wrapper - expect(loggerMock.i.mock.calls).toEqual([['Attempting to disconnect but there are 2 commands still waiting for resolution. Defering disconnection until those finish.']]); + expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 2 commands still waiting for resolution. Defering disconnection until those finish.']]); Promise.all(setToArray(instance._runningCommands)).catch(e => { setImmediate(() => { // Allow the callback to execute before checking. - expect(loggerMock.w.mock.calls[0]).toEqual([`Pending commands finished with error: ${e}. Proceeding with disconnection.`]); // Should warn about the error but tell user that will disconnect anyways. + expect(loggerMock.warn.mock.calls[0]).toEqual([`Pending commands finished with error: ${e}. Proceeding with disconnection.`]); // Should warn about the error but tell user that will disconnect anyways. expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously - loggerMock.i.mockClear(); - loggerMock.w.mockClear(); + loggerMock.info.mockClear(); + loggerMock.warn.mockClear(); ioredisMock.disconnect.mockClear(); // Third run, pending commands all successful @@ -370,11 +370,11 @@ test('STORAGE Redis Adapter / instance methods - _setDisconnectWrapper', (done) instance._runningCommands.add(Promise.resolve()); setTimeout(() => { - expect(loggerMock.i.mock.calls).toEqual([['Attempting to disconnect but there are 4 commands still waiting for resolution. Defering disconnection until those finish.']]); + expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 4 commands still waiting for resolution. Defering disconnection until those finish.']]); Promise.all(setToArray(instance._runningCommands)).then(() => { // This one will go through success path setImmediate(() => { - expect(loggerMock.d.mock.calls).toEqual([['Pending commands finished successfully, disconnecting.']]); + expect(loggerMock.debug.mock.calls).toEqual([['Pending commands finished successfully, disconnecting.']]); expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously }); }); diff --git a/src/storages/inRedis/__tests__/SplitsCacheInRedis.spec.ts b/src/storages/inRedis/__tests__/SplitsCacheInRedis.spec.ts index bcaf990b..1c03268e 100644 --- a/src/storages/inRedis/__tests__/SplitsCacheInRedis.spec.ts +++ b/src/storages/inRedis/__tests__/SplitsCacheInRedis.spec.ts @@ -1,12 +1,13 @@ import Redis from 'ioredis'; import SplitsCacheInRedis from '../SplitsCacheInRedis'; import KeyBuilderSS from '../../KeyBuilderSS'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('SPLITS CACHE / Redis', async () => { const connection = new Redis(); // @ts-expect-error const keys = new KeyBuilderSS(); - const cache = new SplitsCacheInRedis(keys, connection); + const cache = new SplitsCacheInRedis(loggerMock, keys, connection); await cache.clear(); @@ -55,7 +56,7 @@ test('SPLITS CACHE / Redis / trafficTypeExists tests', async () => { const connection = new Redis(); // @ts-expect-error const keys = new KeyBuilderSS(prefix); - const cache = new SplitsCacheInRedis(keys, connection); + const cache = new SplitsCacheInRedis(loggerMock, keys, connection); const testTTName = 'tt_test_name'; const testTTNameNoCount = 'tt_test_name_2'; diff --git a/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts b/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts index 57033e78..2717eeea 100644 --- a/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts +++ b/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts @@ -9,6 +9,7 @@ import splitChangesMock1 from '../../../../__tests__/mocks/splitchanges.since.-1 import fetchMock from '../../../../__tests__/testUtils/fetchMock'; import { settingsSplitApi } from '../../../../utils/settingsValidation/__tests__/settings.mocks'; import EventEmitter from '../../../../utils/MinEvents'; +import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; const activeSplitWithSegments = { name: 'Split1', @@ -55,7 +56,7 @@ test('splitChangesUpdater / compute splits mutation', () => { test('splitChangesUpdater / factory', (done) => { - fetchMock.once('*', { status: 200, body: splitChangesMock1 }); + fetchMock.once('*', { status: 200, body: splitChangesMock1 }); // @ts-ignore const splitApi = splitApiFactory(settingsSplitApi, { getFetch: () => fetchMock, EventEmitter }); const splitChangesFetcher = splitChangesFetcherFactory(splitApi.fetchSplitChanges); @@ -69,7 +70,7 @@ test('splitChangesUpdater / factory', (done) => { const readinessManager = readinessManagerFactory(EventEmitter); const splitsEmitSpy = jest.spyOn(readinessManager.splits, 'emit'); - const splitChangesUpdater = splitChangesUpdaterFactory(splitChangesFetcher, splitsCache, segmentsCache, readinessManager.splits); + const splitChangesUpdater = splitChangesUpdaterFactory(splitChangesFetcher, splitsCache, segmentsCache, readinessManager.splits, 1000, 1, loggerMock); splitChangesUpdater().then((result) => { expect(setChangeNumber.mock.calls.length).toBe(1); diff --git a/src/sync/streaming/AuthClient/__tests__/index.spec.ts b/src/sync/streaming/AuthClient/__tests__/index.spec.ts index 6784439c..98182a59 100644 --- a/src/sync/streaming/AuthClient/__tests__/index.spec.ts +++ b/src/sync/streaming/AuthClient/__tests__/index.spec.ts @@ -9,7 +9,7 @@ import EventEmitter from '../../../../utils/MinEvents'; import { authenticateFactory, hashUserKey } from '../index'; const authorizationKey = settingsSplitApi.core.authorizationKey; -const authUrl = settingsSplitApi.urls.auth; +const authUrl = settingsSplitApi.urls.auth; // @ts-ignore const splitApi = splitApiFactory(settingsSplitApi, { getFetch: () => fetchMock, EventEmitter }); const authenticate = authenticateFactory(splitApi.fetchAuth); diff --git a/src/sync/streaming/SSEHandler/__tests__/index.spec.ts b/src/sync/streaming/SSEHandler/__tests__/index.spec.ts index 1cde90fa..9d7bc038 100644 --- a/src/sync/streaming/SSEHandler/__tests__/index.spec.ts +++ b/src/sync/streaming/SSEHandler/__tests__/index.spec.ts @@ -17,12 +17,13 @@ import occupancy2ControlPri from '../../../../__tests__/mocks/message.OCCUPANCY. import controlStreamingPaused from '../../../../__tests__/mocks/message.CONTROL.STREAMING_PAUSED.control_pri.1586987434750.json'; import controlStreamingResumed from '../../../../__tests__/mocks/message.CONTROL.STREAMING_RESUMED.control_pri.1586987434850.json'; import controlStreamingDisabled from '../../../../__tests__/mocks/message.CONTROL.STREAMING_DISABLED.control_pri.1586987434950.json'; +import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; const pushEmitter = { emit: jest.fn() }; test('`handleOpen` and `handlerMessage` for CONTROL and OCCUPANCY notifications (NotificationKeeper)', () => { pushEmitter.emit.mockClear(); - const sseHandler = SSEHandlerFactory(pushEmitter); + const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); // handleOpen @@ -78,7 +79,7 @@ test('`handleOpen` and `handlerMessage` for CONTROL and OCCUPANCY notifications sseHandler.handleMessage(controlStreamingDisabled); expect(pushEmitter.emit).toHaveBeenLastCalledWith(PUSH_DISABLED); // must emit PUSH_DISABLED if received a STREAMING_RESUMED control message - const sseHandler2 = SSEHandlerFactory(pushEmitter); + const sseHandler2 = SSEHandlerFactory(pushEmitter, loggerMock); sseHandler2.handleOpen(); sseHandler2.handleMessage(controlStreamingPaused); @@ -90,7 +91,7 @@ test('`handleOpen` and `handlerMessage` for CONTROL and OCCUPANCY notifications }); test('`handlerMessage` for update notifications (NotificationProcessor)', () => { - const sseHandler = SSEHandlerFactory(pushEmitter); + const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); sseHandler.handleOpen(); pushEmitter.emit.mockClear(); @@ -113,7 +114,7 @@ test('`handlerMessage` for update notifications (NotificationProcessor)', () => }); test('handleError', () => { - const sseHandler = SSEHandlerFactory(pushEmitter); + const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); sseHandler.handleOpen(); pushEmitter.emit.mockClear(); @@ -134,7 +135,7 @@ test('handleError', () => { }); test('handlerMessage: ignore invalid events', () => { - const sseHandler = SSEHandlerFactory(pushEmitter); + const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); sseHandler.handleOpen(); pushEmitter.emit.mockClear(); diff --git a/src/trackers/__tests__/eventTracker.spec.ts b/src/trackers/__tests__/eventTracker.spec.ts index 57c44655..7c6b11fb 100644 --- a/src/trackers/__tests__/eventTracker.spec.ts +++ b/src/trackers/__tests__/eventTracker.spec.ts @@ -1,3 +1,4 @@ +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; import { SplitIO } from '../../types'; import eventTrackerFactory from '../eventTracker'; @@ -17,7 +18,7 @@ describe('Event Tracker', () => { test('Tracker API', () => { expect(typeof eventTrackerFactory).toBe('function'); // The module should return a function which acts as a factory. - const instance = eventTrackerFactory(fakeEventsCache, fakeIntegrationsManager); + const instance = eventTrackerFactory(loggerMock, fakeEventsCache, fakeIntegrationsManager); expect(typeof instance.track).toBe('function'); // The instance should implement the track method. }); @@ -45,7 +46,7 @@ describe('Event Tracker', () => { } }); - const tracker = eventTrackerFactory(fakeEventsCache, fakeIntegrationsManager); + const tracker = eventTrackerFactory(loggerMock, fakeEventsCache, fakeIntegrationsManager); const result1 = tracker.track(fakeEvent, 1); expect(fakeEventsCache.track.mock.calls[0]).toEqual([fakeEvent, 1]); // Should be present in the event cache. diff --git a/src/trackers/__tests__/impressionsTracker.spec.ts b/src/trackers/__tests__/impressionsTracker.spec.ts index f45de3ed..43988799 100644 --- a/src/trackers/__tests__/impressionsTracker.spec.ts +++ b/src/trackers/__tests__/impressionsTracker.spec.ts @@ -4,6 +4,7 @@ import { impressionObserverSSFactory } from '../impressionObserver/impressionObs import { impressionObserverCSFactory } from '../impressionObserver/impressionObserverCS'; import { IMetadata } from '../../dtos/types'; import { ImpressionDTO } from '../../types'; +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; /* Mocks */ @@ -36,13 +37,13 @@ describe('Impressions Tracker', () => { expect(typeof impressionsTrackerFactory).toBe('function'); // The module should return a function which acts as a factory. const { fakeImpressionsCache, fakeMetadata } = generateMocks(); - const instance = impressionsTrackerFactory(fakeImpressionsCache, fakeMetadata); + const instance = impressionsTrackerFactory(loggerMock, fakeImpressionsCache, fakeMetadata); expect(typeof instance.track).toBe('function'); // The instance should implement the track method which will actually track queued impressions. }); test('Should be able to track impressions (in DEBUG mode without Previous Time).', () => { const { fakeImpressionsCache, fakeMetadata } = generateMocks(); - const tracker = impressionsTrackerFactory(fakeImpressionsCache, fakeMetadata); + const tracker = impressionsTrackerFactory(loggerMock, fakeImpressionsCache, fakeMetadata); const imp1 = { feature: '10', @@ -63,7 +64,7 @@ describe('Impressions Tracker', () => { test('Tracked impressions should be sent to impression listener and integration manager when we invoke .track()', (done) => { const { fakeImpressionsCache, fakeMetadata, fakeListener, fakeIntegrationsManager } = generateMocks(); - const tracker = impressionsTrackerFactory(fakeImpressionsCache, fakeMetadata, fakeListener, fakeIntegrationsManager); + const tracker = impressionsTrackerFactory(loggerMock, fakeImpressionsCache, fakeMetadata, fakeListener, fakeIntegrationsManager); const fakeImpression = { feature: 'impression' @@ -138,8 +139,8 @@ describe('Impressions Tracker', () => { impression3.time = 1234567891; const trackers = [ - impressionsTrackerFactory(fakeImpressionsCache, fakeMetadata, undefined, undefined, impressionObserverSSFactory()), - impressionsTrackerFactory(fakeImpressionsCache, fakeMetadata, undefined, undefined, impressionObserverCSFactory()) + impressionsTrackerFactory(loggerMock, fakeImpressionsCache, fakeMetadata, undefined, undefined, impressionObserverSSFactory()), + impressionsTrackerFactory(loggerMock, fakeImpressionsCache, fakeMetadata, undefined, undefined, impressionObserverCSFactory()) ]; expect(fakeImpressionsCache.track.mock.calls.length).toBe(0); // storage method should not be called until impressions are tracked. @@ -167,7 +168,7 @@ describe('Impressions Tracker', () => { impression3.time = Date.now(); const impressionCountsCache = new ImpressionCountsCacheInMemory(); - const tracker = impressionsTrackerFactory(fakeImpressionsCache, fakeMetadata, undefined, undefined, impressionObserverCSFactory(), impressionCountsCache); + const tracker = impressionsTrackerFactory(loggerMock, fakeImpressionsCache, fakeMetadata, undefined, undefined, impressionObserverCSFactory(), impressionCountsCache); expect(fakeImpressionsCache.track.mock.calls.length).toBe(0); // cache method should not be called by just creating a tracker diff --git a/src/utils/inputValidation/__tests__/apiKey.spec.ts b/src/utils/inputValidation/__tests__/apiKey.spec.ts index 8ebceaba..a5c3e908 100644 --- a/src/utils/inputValidation/__tests__/apiKey.spec.ts +++ b/src/utils/inputValidation/__tests__/apiKey.spec.ts @@ -28,8 +28,8 @@ describe('validateApiKey', () => { test('Should return the passed api key if it is a valid string without logging any errors', () => { const validApiKey = 'qjok3snti4dgsticade5hfphmlucarsflv14'; - expect(validateApiKey(validApiKey)).toBe(validApiKey); // It should return the passed string if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateApiKey(loggerMock, validApiKey)).toBe(validApiKey); // It should return the passed string if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. mockClear(); }); @@ -39,10 +39,10 @@ describe('validateApiKey', () => { const invalidApiKey = invalidKeys[i]['key']; const expectedLog = invalidKeys[i]['msg']; - expect(validateApiKey(invalidApiKey)).toBe(false); // Invalid strings should return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual(expectedLog); // The error should be logged for the invalid string. + expect(validateApiKey(loggerMock, invalidApiKey)).toBe(false); // Invalid strings should return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual(expectedLog); // The error should be logged for the invalid string. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } mockClear(); @@ -56,14 +56,14 @@ describe('validateAndTrackApiKey', () => { const validApiKey2 = 'qjok3snti4dgsticade5hfphmlucars92uih'; const validApiKey3 = '84ynbsnti4dgsticade5hfphmlucars92uih'; - expect(validateAndTrackApiKey(validApiKey1)).toBe(validApiKey1); - expect(loggerMock.w.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. + expect(validateAndTrackApiKey(loggerMock, validApiKey1)).toBe(validApiKey1); + expect(loggerMock.warn.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. - expect(validateAndTrackApiKey(validApiKey2)).toBe(validApiKey2); - expect(loggerMock.w.mock.calls).toEqual([['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a new api key, we get a warning. + expect(validateAndTrackApiKey(loggerMock, validApiKey2)).toBe(validApiKey2); + expect(loggerMock.warn.mock.calls).toEqual([['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a new api key, we get a warning. - expect(validateAndTrackApiKey(validApiKey3)).toBe(validApiKey3); - expect(loggerMock.w.mock.calls[0]).toEqual(['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']); // We register a new api key, we get a warning. + expect(validateAndTrackApiKey(loggerMock, validApiKey3)).toBe(validApiKey3); + expect(loggerMock.warn.mock.calls[0]).toEqual(['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']); // We register a new api key, we get a warning. // We will release the used keys and expect no warnings next time. releaseApiKey(validApiKey1); @@ -72,8 +72,8 @@ describe('validateAndTrackApiKey', () => { mockClear(); - expect(validateAndTrackApiKey(validApiKey1)).toBe(validApiKey1); - expect(loggerMock.w.mock.calls.length).toBe(0); // If all the keys were released and we try again, there is no warning. + expect(validateAndTrackApiKey(loggerMock, validApiKey1)).toBe(validApiKey1); + expect(loggerMock.warn.mock.calls.length).toBe(0); // If all the keys were released and we try again, there is no warning. releaseApiKey(validApiKey1); // clean up the cache of api keys for next test mockClear(); @@ -82,18 +82,18 @@ describe('validateAndTrackApiKey', () => { test('Should log a warning if we are instantiating more than one factory (same api key)', () => { const validApiKey = '84ynbsnti4dgsticade5hfphmlucars92uih'; - expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); - expect(loggerMock.w.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. + expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); + expect(loggerMock.warn.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. - expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); + expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); // Same key one more time, 2 instances plus new one. - expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); + expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); // Same key one more time, 3 instances plus new one. - expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); + expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); - expect(loggerMock.w.mock.calls).toEqual([ + expect(loggerMock.warn.mock.calls).toEqual([ ['Factory instantiation: You already have 1 factory with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'], // We register a the same api key again, we get a warning with the number of instances we have. ['Factory instantiation: You already have 2 factories with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'], // We register a the same api key again, we get a warning with the number of instances we have. ['Factory instantiation: You already have 3 factories with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'] // We register a the same api key again, we get a warning with the number of instances we have. @@ -107,8 +107,8 @@ describe('validateAndTrackApiKey', () => { mockClear(); // So we get the warning again. - expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); - expect(loggerMock.w.mock.calls).toEqual([['Factory instantiation: You already have 1 factory with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a the same api key again, we get a warning with the number of instances we have. + expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); + expect(loggerMock.warn.mock.calls).toEqual([['Factory instantiation: You already have 1 factory with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a the same api key again, we get a warning with the number of instances we have. // Leave it with 0 releaseApiKey(validApiKey); @@ -116,8 +116,8 @@ describe('validateAndTrackApiKey', () => { mockClear(); - expect(validateAndTrackApiKey(validApiKey)).toBe(validApiKey); - expect(loggerMock.w.mock.calls.length).toBe(0); // s users, there is no warning when we use it again. + expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); + expect(loggerMock.warn.mock.calls.length).toBe(0); // s users, there is no warning when we use it again. releaseApiKey(validApiKey); // clean up the cache just in case a new test is added mockClear(); diff --git a/src/utils/inputValidation/__tests__/attributes.spec.ts b/src/utils/inputValidation/__tests__/attributes.spec.ts index 4c395dc2..17356188 100644 --- a/src/utils/inputValidation/__tests__/attributes.spec.ts +++ b/src/utils/inputValidation/__tests__/attributes.spec.ts @@ -21,18 +21,18 @@ describe('INPUT VALIDATION for Attributes', () => { test('Should return the passed object if it is a valid attributes map without logging any errors', () => { const validAttributes = { amIvalid: 'yes', 'are_you_sure': true, howMuch: 10 }; - expect(validateAttributes(validAttributes, 'some_method_attrs')).toEqual(validAttributes); // It should return the passed map if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(validateAttributes(loggerMock, validAttributes, 'some_method_attrs')).toEqual(validAttributes); // It should return the passed map if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear; }); test('Should return the passed value if it is null or undefined (since attributes are optional) without logging any errors', () => { - expect(validateAttributes(null, 'some_method_attrs')).toBe(null); // It should return the passed null. - expect(validateAttributes(undefined, 'some_method_attrs')).toBe(undefined); // It should return the passed undefined. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(validateAttributes(loggerMock, null, 'some_method_attrs')).toBe(null); // It should return the passed null. + expect(validateAttributes(loggerMock, undefined, 'some_method_attrs')).toBe(undefined); // It should return the passed undefined. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -41,13 +41,13 @@ describe('INPUT VALIDATION for Attributes', () => { for (let i = 0; i < invalidAttributes.length; i++) { const invalidAttribute = invalidAttributes[i]; - expect(validateAttributes(invalidAttribute, 'test_method')).toBe(false); // Invalid attribute objects should return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual('test_method: attributes must be a plain object.'); // The error should be logged for the invalid attributes map. + expect(validateAttributes(loggerMock, invalidAttribute, 'test_method')).toBe(false); // Invalid attribute objects should return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual('test_method: attributes must be a plain object.'); // The error should be logged for the invalid attributes map. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/event.spec.ts b/src/utils/inputValidation/__tests__/event.spec.ts index a5f1c4b2..4c6c9b57 100644 --- a/src/utils/inputValidation/__tests__/event.spec.ts +++ b/src/utils/inputValidation/__tests__/event.spec.ts @@ -35,14 +35,14 @@ describe('INPUT VALIDATION for Event types', () => { test('Should return the provided event type if it is a valid string without logging any errors', () => { - expect(validateEvent('valid:Too', 'some_method_eventType')).toBe('valid:Too'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(validateEvent('I.am.valid-string_ValUe', 'some_method_eventType')).toBe('I.am.valid-string_ValUe'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(validateEvent('a', 'some_method_eventType')).toBe('a'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateEvent(loggerMock, 'valid:Too', 'some_method_eventType')).toBe('valid:Too'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateEvent(loggerMock, 'I.am.valid-string_ValUe', 'some_method_eventType')).toBe('I.am.valid-string_ValUe'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateEvent(loggerMock, 'a', 'some_method_eventType')).toBe('a'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -52,13 +52,13 @@ describe('INPUT VALIDATION for Event types', () => { const invalidValue = invalidEvents[i]['event']; const expectedLog = invalidEvents[i]['msg'](invalidValue); - expect(validateEvent(invalidValue, 'test_method')).toBe(false); // Invalid event types should always return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. + expect(validateEvent(loggerMock, invalidValue, 'test_method')).toBe(false); // Invalid event types should always return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/eventProperties.spec.ts b/src/utils/inputValidation/__tests__/eventProperties.spec.ts index 9749989a..08dd5d51 100644 --- a/src/utils/inputValidation/__tests__/eventProperties.spec.ts +++ b/src/utils/inputValidation/__tests__/eventProperties.spec.ts @@ -35,19 +35,19 @@ const invalidValues = [ describe('INPUT VALIDATION for Event Properties', () => { test('Not setting the properties object is acceptable', () => { - expect(validateEventProperties(undefined, 'some_method_eventProps')).toEqual({ + expect(validateEventProperties(loggerMock, undefined, 'some_method_eventProps')).toEqual({ properties: null, size: 1024 }); // It should return null in replacement of undefined since it is valid with default event size.'); - expect(validateEventProperties(undefined, 'some_method_eventProps')).toEqual({ + expect(validateEventProperties(loggerMock, undefined, 'some_method_eventProps')).toEqual({ properties: null, size: 1024 }); // It should return the passed null since it is valid with default event size.'); - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -55,16 +55,16 @@ describe('INPUT VALIDATION for Event Properties', () => { test('When setting a value for properties, only objects are acceptable', () => { invalidValues.forEach(val => { - expect(validateEventProperties(val, 'some_method_eventProps')).toEqual({ + expect(validateEventProperties(loggerMock, val, 'some_method_eventProps')).toEqual({ properties: false, size: 1024 }); // It should return default size and properties false if the properties value is not an object or null/undefined.'); - expect(loggerMock.e.mock.calls).toEqual([['some_method_eventProps: properties must be a plain object.']]); // Should log an error. - loggerMock.e.mockClear(); + expect(loggerMock.error.mock.calls).toEqual([['some_method_eventProps: properties must be a plain object.']]); // Should log an error. + loggerMock.error.mockClear(); }); - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -79,7 +79,7 @@ describe('INPUT VALIDATION for Event Properties', () => { number2: 0.250, nullProp: null }; - const output = validateEventProperties(validProperties, 'some_method_eventProps'); + const output = validateEventProperties(loggerMock, validProperties, 'some_method_eventProps'); expect(output).toEqual({ properties: validProperties, @@ -89,8 +89,8 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(validProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -108,7 +108,7 @@ describe('INPUT VALIDATION for Event Properties', () => { willBeNulled3: [], willBeNulled4: new Map() }; - const output = validateEventProperties(providedProperties, 'some_method_eventProps'); + const output = validateEventProperties(loggerMock, providedProperties, 'some_method_eventProps'); expect(output).toEqual({ properties: { @@ -121,11 +121,11 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(providedProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(4); // It should have logged one warning per each property of the invalid type. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(4); // It should have logged one warning per each property of the invalid type. ['willBeNulled1', 'willBeNulled2', 'willBeNulled3', 'willBeNulled4'].forEach((key, index) => { - expect(loggerMock.w.mock.calls[index][0]).toBe(`some_method_eventProps: Property ${key} is of invalid type. Setting value to null.`); + expect(loggerMock.warn.mock.calls[index][0]).toBe(`some_method_eventProps: Property ${key} is of invalid type. Setting value to null.`); }); mockClear(); @@ -137,7 +137,7 @@ describe('INPUT VALIDATION for Event Properties', () => { for (let i = 0; i < 300; i++) { validProperties[i] = null; // all will be null so we do not exceed the size. } - let output = validateEventProperties(validProperties, 'some_method_eventProps'); + let output = validateEventProperties(loggerMock, validProperties, 'some_method_eventProps'); expect(output).toEqual({ properties: validProperties, @@ -145,12 +145,12 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return the properties and the event size.'); - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. // @ts-ignore validProperties.a = null; // Adding one prop to exceed the limit. - output = validateEventProperties(validProperties, 'some_method_eventProps'); + output = validateEventProperties(loggerMock, validProperties, 'some_method_eventProps'); expect(output).toEqual({ properties: validProperties, @@ -158,8 +158,8 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return the properties and the event size.'); - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls).toEqual([['some_method_eventProps: Event has more than 300 properties. Some of them will be trimmed when processed.']]); // It should have logged a warning. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls).toEqual([['some_method_eventProps: Event has more than 300 properties. Some of them will be trimmed when processed.']]); // It should have logged a warning. mockClear(); }); @@ -173,7 +173,7 @@ describe('INPUT VALIDATION for Event Properties', () => { validProperties[i] = fiveHundredChars; // key length is two, plus 510 chars it is 512 which multiplied by the byte size of each char is 1kb each key. } // It should be right on the size limit. - let output = validateEventProperties(validProperties, 'some_method_eventProps'); + let output = validateEventProperties(loggerMock, validProperties, 'some_method_eventProps'); expect(output).toEqual({ properties: validProperties, @@ -182,13 +182,13 @@ describe('INPUT VALIDATION for Event Properties', () => { // It should return the properties and the event size.'); expect(validProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // Should not log any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. // @ts-ignore validProperties.a = null; // exceed by two bytes (1 char string key which is two bytes, null value which we count as 0 to match other SDKs) - output = validateEventProperties(validProperties, 'some_method_eventProps'); + output = validateEventProperties(loggerMock, validProperties, 'some_method_eventProps'); expect(output).toEqual({ properties: false, @@ -196,10 +196,10 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return false instead of the properties and the event size.'); - expect(loggerMock.w.mock.calls.length).toBe(0); // Should not log any warnings. - expect(loggerMock.e.mock.calls).toEqual([['some_method_eventProps: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.']]); // Should log an error. + expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. + expect(loggerMock.error.mock.calls).toEqual([['some_method_eventProps: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.']]); // Should log an error. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/eventValue.spec.ts b/src/utils/inputValidation/__tests__/eventValue.spec.ts index c3f28dea..900d9eae 100644 --- a/src/utils/inputValidation/__tests__/eventValue.spec.ts +++ b/src/utils/inputValidation/__tests__/eventValue.spec.ts @@ -20,23 +20,23 @@ const invalidValues = [ describe('INPUT VALIDATION for Event Values', () => { test('Should return the passed value if it is a valid finite number without logging any errors', () => { - expect(validateEventValue(50, 'some_method_eventValue')).toBe(50); // It should return the passed number if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(validateEventValue(-50, 'some_method_eventValue')).toBe(-50); // It should return the passed number if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateEventValue(loggerMock, 50, 'some_method_eventValue')).toBe(50); // It should return the passed number if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateEventValue(loggerMock, -50, 'some_method_eventValue')).toBe(-50); // It should return the passed number if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); test('Should return the passed value if it is a null or undefined (since it is optional) without logging any errors', () => { - expect(validateEventValue(null, 'some_method_eventValue')).toBe(null); // It should return the passed number if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(validateEventValue(undefined, 'some_method_eventValue')).toBe(undefined); // It should return the passed number if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateEventValue(loggerMock, null, 'some_method_eventValue')).toBe(null); // It should return the passed number if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateEventValue(loggerMock, undefined, 'some_method_eventValue')).toBe(undefined); // It should return the passed number if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -45,13 +45,13 @@ describe('INPUT VALIDATION for Event Values', () => { for (let i = 0; i < invalidValues.length; i++) { const invalidValue = invalidValues[i]; - expect(validateEventValue(invalidValue, 'test_method')).toBe(false); // Invalid event values should always return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual('test_method: value must be a finite number.'); // Should log the error for the invalid event value. + expect(validateEventValue(loggerMock, invalidValue, 'test_method')).toBe(false); // Invalid event values should always return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual('test_method: value must be a finite number.'); // Should log the error for the invalid event value. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/isOperational.spec.ts b/src/utils/inputValidation/__tests__/isOperational.spec.ts index fe44ebdd..5bdcb3b9 100644 --- a/src/utils/inputValidation/__tests__/isOperational.spec.ts +++ b/src/utils/inputValidation/__tests__/isOperational.spec.ts @@ -8,10 +8,10 @@ describe('validateIfNotDestroyed', () => { const readinessManagerMock = { isDestroyed: jest.fn(() => false) }; // @ts-ignore - expect(validateIfNotDestroyed(readinessManagerMock)).toBe(true); // It should return true if the client is operational (it is NOT destroyed). + expect(validateIfNotDestroyed(loggerMock, readinessManagerMock)).toBe(true); // It should return true if the client is operational (it is NOT destroyed). expect(readinessManagerMock.isDestroyed.mock.calls.length).toBe(1); // It checks for destroyed status using the context. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // Should not log any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. mockClear(); }); @@ -20,10 +20,10 @@ describe('validateIfNotDestroyed', () => { const readinessManagerMock = { isDestroyed: jest.fn(() => true) }; // @ts-ignore - expect(validateIfNotDestroyed(readinessManagerMock)).toBe(false); // It should return false if the client is NOT operational (it is destroyed). + expect(validateIfNotDestroyed(loggerMock, readinessManagerMock)).toBe(false); // It should return false if the client is NOT operational (it is destroyed). expect(readinessManagerMock.isDestroyed.mock.calls.length).toBe(1); // It checks for destroyed status using the context. - expect(loggerMock.e.mock.calls).toEqual([['Client has already been destroyed - no calls possible.']]); // Should log an error. - expect(loggerMock.w.mock.calls.length).toBe(0); // But it should not log any warnings. + expect(loggerMock.error.mock.calls).toEqual([['Client has already been destroyed - no calls possible.']]); // Should log an error. + expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. mockClear(); }); @@ -35,10 +35,10 @@ describe('validateIfOperational', () => { const readinessManagerMock = { isReady: jest.fn(() => true) }; // @ts-ignore - expect(validateIfOperational(readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready. + expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready. expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for readiness status using the context. - expect(loggerMock.w.mock.calls.length).toBe(0); // But it should not log any warnings. - expect(loggerMock.e.mock.calls.length).toBe(0); // But it should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. mockClear(); }); @@ -47,11 +47,11 @@ describe('validateIfOperational', () => { const readinessManagerMock = { isReady: jest.fn(() => false), isReadyFromCache: jest.fn(() => true) }; // @ts-ignore - expect(validateIfOperational(readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready. + expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready. expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for SDK_READY status. expect(readinessManagerMock.isReadyFromCache.mock.calls.length).toBe(1); // It checks for SDK_READY_FROM_CACHE status. - expect(loggerMock.w.mock.calls.length).toBe(0); // But it should not log any warnings. - expect(loggerMock.e.mock.calls.length).toBe(0); // But it should not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. mockClear(); }); @@ -60,11 +60,11 @@ describe('validateIfOperational', () => { const readinessManagerMock = { isReady: jest.fn(() => false), isReadyFromCache: jest.fn(() => false) }; // @ts-ignore - expect(validateIfOperational(readinessManagerMock, 'test_method')).toBe(false); // It should return true if SDK was ready. + expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(false); // It should return true if SDK was ready. expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for SDK_READY status. expect(readinessManagerMock.isReadyFromCache.mock.calls.length).toBe(1); // It checks for SDK_READY_FROM_CACHE status. - expect(loggerMock.w.mock.calls).toEqual([['test_method: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.']]); // It should log the expected warning. - expect(loggerMock.e.mock.calls.length).toBe(0); // But it should not log any errors. + expect(loggerMock.warn.mock.calls).toEqual([['test_method: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.']]); // It should log the expected warning. + expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/key.spec.ts b/src/utils/inputValidation/__tests__/key.spec.ts index 9879f7ed..703242b5 100644 --- a/src/utils/inputValidation/__tests__/key.spec.ts +++ b/src/utils/inputValidation/__tests__/key.spec.ts @@ -48,13 +48,13 @@ describe('INPUT VALIDATION for Key', () => { matchingKey: 'valid', bucketingKey: 'alsoValid' }; - expect(validateKey(validKey, 'some_method_keys')).toEqual(validKey); // It will return the valid key. - expect(loggerMock.e.mock.calls.length).toBe(0); // No errors should be logged. + expect(validateKey(loggerMock, validKey, 'some_method_keys')).toEqual(validKey); // It will return the valid key. + expect(loggerMock.error.mock.calls.length).toBe(0); // No errors should be logged. - expect(validateKey(validObjKey, 'some_method_keys')).toEqual(validObjKey); // It will return the valid key. - expect(loggerMock.e.mock.calls.length).toBe(0); // No errors should be logged. + expect(validateKey(loggerMock, validObjKey, 'some_method_keys')).toEqual(validObjKey); // It will return the valid key. + expect(loggerMock.error.mock.calls.length).toBe(0); // No errors should be logged. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -64,13 +64,13 @@ describe('INPUT VALIDATION for Key', () => { const invalidKey = invalidKeys[i]['key']; const expectedLog = invalidKeys[i]['msg']('key'); - expect(validateKey(invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(validateKey(loggerMock, invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -80,13 +80,13 @@ describe('INPUT VALIDATION for Key', () => { const invalidKey = stringifyableKeys[i]['key']; const expectedLog = stringifyableKeys[i]['msg']('key', invalidKey); - validateKey(invalidKey, 'test_method'); - expect(loggerMock.w.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // But if the logger allows for warnings, it should be logged. + validateKey(loggerMock, invalidKey, 'test_method'); + expect(loggerMock.warn.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // But if the logger allows for warnings, it should be logged. - loggerMock.w.mockClear(); + loggerMock.warn.mockClear(); } - expect(loggerMock.e.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. mockClear(); }); @@ -94,13 +94,13 @@ describe('INPUT VALIDATION for Key', () => { test('Object key / Should return false and log error if a part of the key is invalid', () => { // Test invalid object format for (let i = 0; i < invalidKeyObjects.length; i++) { - expect(validateKey(invalidKeyObjects[i], 'test_method')).toBe(false); // Invalid key objects should return false. - expect(loggerMock.e.mock.calls[loggerMock.e.mock.calls.length - 1][0]).toEqual(`test_method: ${errorMsgs.WRONG_KEY_PROPS}`); // The error should be logged for the invalid key. + expect(validateKey(loggerMock, invalidKeyObjects[i], 'test_method')).toBe(false); // Invalid key objects should return false. + expect(loggerMock.error.mock.calls[loggerMock.error.mock.calls.length - 1][0]).toEqual(`test_method: ${errorMsgs.WRONG_KEY_PROPS}`); // The error should be logged for the invalid key. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); // Test invalid matchingKey @@ -111,13 +111,13 @@ describe('INPUT VALIDATION for Key', () => { }; const expectedLog = invalidKeys[i]['msg']('matchingKey'); - expect(validateKey(invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(validateKey(loggerMock, invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); @@ -129,13 +129,13 @@ describe('INPUT VALIDATION for Key', () => { }; const expectedLog = invalidKeys[i]['msg']('bucketingKey'); - expect(validateKey(invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(validateKey(loggerMock, invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); @@ -147,11 +147,11 @@ describe('INPUT VALIDATION for Key', () => { let expectedLogMK = invalidKeys[0]['msg']('matchingKey'); let expectedLogBK = invalidKeys[1]['msg']('bucketingKey'); - expect(validateKey(invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The error should be logged for the invalid key property. - expect(loggerMock.e.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The error should be logged for the invalid key property. + expect(validateKey(loggerMock, invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The error should be logged for the invalid key property. + expect(loggerMock.error.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The error should be logged for the invalid key property. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -168,11 +168,11 @@ describe('INPUT VALIDATION for Key', () => { let expectedLogMK = stringifyableKeys[0]['msg']('matchingKey', invalidKey.matchingKey); let expectedLogBK = stringifyableKeys[1]['msg']('bucketingKey', invalidKey.bucketingKey); - expect(validateKey(invalidKey, 'test_method')).toEqual(expectedKey); // If a key object had stringifyable values, those will be stringified and Key returned. - expect(loggerMock.w.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The warning should be logged for the stringified prop if warnings are enabled. - expect(loggerMock.w.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The warning should be logged for the stringified prop if warnings are enabled. + expect(validateKey(loggerMock, invalidKey, 'test_method')).toEqual(expectedKey); // If a key object had stringifyable values, those will be stringified and Key returned. + expect(loggerMock.warn.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The warning should be logged for the stringified prop if warnings are enabled. + expect(loggerMock.warn.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The warning should be logged for the stringified prop if warnings are enabled. - expect(loggerMock.e.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/preloadedData.spec.ts b/src/utils/inputValidation/__tests__/preloadedData.spec.ts index 4dd26568..248aaf12 100644 --- a/src/utils/inputValidation/__tests__/preloadedData.spec.ts +++ b/src/utils/inputValidation/__tests__/preloadedData.spec.ts @@ -138,20 +138,20 @@ test('INPUT VALIDATION for preloadedData', () => { for (let i = 0; i < testCases.length; i++) { const testCase = testCases[i]; - expect(validatePreloadedData(testCase.input, method)).toBe(testCase.output); + expect(validatePreloadedData(loggerMock, testCase.input, method)).toBe(testCase.output); if (testCase.error) { - expect(loggerMock.e.mock.calls[0]).toEqual([testCase.error]); // Should log the error for the invalid preloadedData. - loggerMock.e.mockClear(); + expect(loggerMock.error.mock.calls[0]).toEqual([testCase.error]); // Should log the error for the invalid preloadedData. + loggerMock.error.mockClear(); } else { - expect(loggerMock.e.mock.calls.length === 0).toBe(true); // Should not log any error. + expect(loggerMock.error.mock.calls.length === 0).toBe(true); // Should not log any error. } if (testCase.warn) { - expect(loggerMock.w.mock.calls[0]).toEqual([testCase.warn]); // Should log the warning for the given preloadedData. - loggerMock.w.mockClear(); + expect(loggerMock.warn.mock.calls[0]).toEqual([testCase.warn]); // Should log the warning for the given preloadedData. + loggerMock.warn.mockClear(); } else { - expect(loggerMock.w.mock.calls.length === 0).toBe(true); // Should not log any warning. + expect(loggerMock.warn.mock.calls.length === 0).toBe(true); // Should not log any warning. } } }); diff --git a/src/utils/inputValidation/__tests__/split.spec.ts b/src/utils/inputValidation/__tests__/split.spec.ts index cffb37cb..b3afbfe5 100644 --- a/src/utils/inputValidation/__tests__/split.spec.ts +++ b/src/utils/inputValidation/__tests__/split.spec.ts @@ -36,14 +36,14 @@ const trimmableSplits = [ describe('INPUT VALIDATION for Split name', () => { test('Should return the provided split name if it is a valid string without logging any errors', () => { - expect(validateSplit('splitName', 'some_method_splitName')).toBe('splitName'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. - expect(validateSplit('split_name', 'some_method_splitName')).toBe('split_name'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. - expect(validateSplit('A_split-name_29', 'some_method_splitName')).toBe('A_split-name_29'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. + expect(validateSplit(loggerMock, 'splitName', 'some_method_splitName')).toBe('splitName'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. + expect(validateSplit(loggerMock, 'split_name', 'some_method_splitName')).toBe('split_name'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. + expect(validateSplit(loggerMock, 'A_split-name_29', 'some_method_splitName')).toBe('A_split-name_29'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -51,13 +51,13 @@ describe('INPUT VALIDATION for Split name', () => { test('Should trim split name if it is a valid string with trimmable spaces and log a warning (if those are enabled)', () => { for (let i = 0; i < trimmableSplits.length; i++) { const trimmableSplit = trimmableSplits[i]; - expect(validateSplit(trimmableSplit, 'some_method_splitName')).toBe(trimmableSplit.trim()); // It should return the trimmed version of the split name received. - expect(loggerMock.w.mock.calls[0][0]).toEqual(`some_method_splitName: ${errorMsgs.TRIMMABLE_SPLIT(trimmableSplit)}`); // Should log a warning if those are enabled. + expect(validateSplit(loggerMock, trimmableSplit, 'some_method_splitName')).toBe(trimmableSplit.trim()); // It should return the trimmed version of the split name received. + expect(loggerMock.warn.mock.calls[0][0]).toEqual(`some_method_splitName: ${errorMsgs.TRIMMABLE_SPLIT(trimmableSplit)}`); // Should log a warning if those are enabled. - loggerMock.w.mockClear(); + loggerMock.warn.mockClear(); } - expect(loggerMock.e.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. mockClear(); }); @@ -68,13 +68,13 @@ describe('INPUT VALIDATION for Split name', () => { // @ts-ignore const expectedLog = invalidSplits[i]['msg'](invalidValue); - expect(validateSplit(invalidValue, 'test_method')).toBe(false); // Invalid event types should always return false. - expect(loggerMock.e.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. + expect(validateSplit(loggerMock, invalidValue, 'test_method')).toBe(false); // Invalid event types should always return false. + expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/splitExistance.spec.ts b/src/utils/inputValidation/__tests__/splitExistance.spec.ts index 642c651e..c1f25d2c 100644 --- a/src/utils/inputValidation/__tests__/splitExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/splitExistance.spec.ts @@ -18,32 +18,32 @@ describe('Split existance (special case)', () => { isReady: jest.fn(() => false) // Fake the signal for the non ready SDK } as IReadinessManager; - expect(validateSplitExistance(readinessManagerMock, 'some_split', {}, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. - expect(validateSplitExistance(readinessManagerMock, 'some_split', null, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. - expect(validateSplitExistance(readinessManagerMock, 'some_split', undefined, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. - expect(validateSplitExistance(readinessManagerMock, 'some_split', 'a label', 'test_method')).toBe(true); // Should always return true when the SDK is not ready. - expect(validateSplitExistance(readinessManagerMock, 'some_split', LabelConstants.SPLIT_NOT_FOUND, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'some_split', {}, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'some_split', null, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'some_split', undefined, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'some_split', 'a label', 'test_method')).toBe(true); // Should always return true when the SDK is not ready. + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'some_split', LabelConstants.SPLIT_NOT_FOUND, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. - expect(loggerMock.w.mock.calls.length).toBe(0); // There should have been no warning logs since the SDK was not ready yet. - expect(loggerMock.e.mock.calls.length).toBe(0); // There should have been no error logs since the SDK was not ready yet. + expect(loggerMock.warn.mock.calls.length).toBe(0); // There should have been no warning logs since the SDK was not ready yet. + expect(loggerMock.error.mock.calls.length).toBe(0); // There should have been no error logs since the SDK was not ready yet. // Prepare the mock to fake that the SDK is ready now. (readinessManagerMock.isReady as jest.Mock).mockImplementation(() => true); - expect(validateSplitExistance(readinessManagerMock, 'other_split', {}, 'other_method')).toBe(true); // Should return true if it receives a Split Object instead of null (when the object is not found, for manager). - expect(validateSplitExistance(readinessManagerMock, 'other_split', 'a label', 'other_method')).toBe(true); // Should return true if it receives a Label and it is not split not found (when the Split was not found on the storage, for client). + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', {}, 'other_method')).toBe(true); // Should return true if it receives a Split Object instead of null (when the object is not found, for manager). + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', 'a label', 'other_method')).toBe(true); // Should return true if it receives a Label and it is not split not found (when the Split was not found on the storage, for client). - expect(loggerMock.w.mock.calls.length).toBe(0); // There should have been no warning logs since the values we used so far were considered valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // There should have been no error logs since the values we used so far were considered valid. + expect(loggerMock.warn.mock.calls.length).toBe(0); // There should have been no warning logs since the values we used so far were considered valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // There should have been no error logs since the values we used so far were considered valid. - expect(validateSplitExistance(readinessManagerMock, 'other_split', null, 'other_method')).toBe(false); // Should return false if it receives a non-truthy value as a split object or label - expect(validateSplitExistance(readinessManagerMock, 'other_split', undefined, 'other_method')).toBe(false); // Should return false if it receives a non-truthy value as a split object or label - expect(validateSplitExistance(readinessManagerMock, 'other_split', LabelConstants.SPLIT_NOT_FOUND, 'other_method')).toBe(false); // Should return false if it receives a label but it is the split not found one. + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', null, 'other_method')).toBe(false); // Should return false if it receives a non-truthy value as a split object or label + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', undefined, 'other_method')).toBe(false); // Should return false if it receives a non-truthy value as a split object or label + expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', LabelConstants.SPLIT_NOT_FOUND, 'other_method')).toBe(false); // Should return false if it receives a label but it is the split not found one. - expect(loggerMock.w.mock.calls.length).toBe(3); // It should have logged 3 warnings, one per each time we called it - loggerMock.w.mock.calls.forEach(call => expect(call[0]).toBe(`other_method: ${errorMsgs.NOT_EXISTENT_SPLIT('other_split')}`)); // Warning logs should have the correct message. + expect(loggerMock.warn.mock.calls.length).toBe(3); // It should have logged 3 warnings, one per each time we called it + loggerMock.warn.mock.calls.forEach(call => expect(call[0]).toBe(`other_method: ${errorMsgs.NOT_EXISTENT_SPLIT('other_split')}`)); // Warning logs should have the correct message. - expect(loggerMock.e.mock.calls.length).toBe(0); // We log warnings, not errors. + expect(loggerMock.error.mock.calls.length).toBe(0); // We log warnings, not errors. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/splits.spec.ts b/src/utils/inputValidation/__tests__/splits.spec.ts index 8e8df37b..eba948d3 100644 --- a/src/utils/inputValidation/__tests__/splits.spec.ts +++ b/src/utils/inputValidation/__tests__/splits.spec.ts @@ -8,7 +8,7 @@ import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock' jest.mock('../split'); import { validateSplit } from '../split'; const validateSplitMock = validateSplit as jest.Mock; -validateSplitMock.mockImplementation((maybeSplit) => maybeSplit); +validateSplitMock.mockImplementation((_, maybeSplit) => maybeSplit); // test target import { validateSplits } from '../splits'; @@ -41,47 +41,47 @@ describe('INPUT VALIDATION for Split names', () => { test('Should return the provided array if it is a valid splits names array without logging any errors', () => { const validArr = ['splitName1', 'split_name_2', 'split-name-3']; - expect(validateSplits(validArr, 'some_method_splits')).toEqual(validArr); // It should return the provided array without changes if it is valid. + expect(validateSplits(loggerMock, validArr, 'some_method_splits')).toEqual(validArr); // It should return the provided array without changes if it is valid. expect(validateSplitMock.mock.calls.length).toBe(validArr.length); // Should have validated each value independently. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors on the collection. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors on the collection. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. }); test('Should return the provided array if it is a valid splits names array removing duplications, without logging any errors', () => { const validArr = ['split_name', 'split_name', 'split-name']; - expect(validateSplits(validArr, 'some_method_splits')).toEqual(uniq(validArr)); // It should return the provided array without changes if it is valid. + expect(validateSplits(loggerMock, validArr, 'some_method_splits')).toEqual(uniq(validArr)); // It should return the provided array without changes if it is valid. expect(validateSplitMock.mock.calls.length).toBe(validArr.length); // Should have validated each value independently. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors on the collection. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors on the collection. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. }); test('Should return false and log an error for the array if it is invalid', () => { for (let i = 0; i < invalidSplits.length; i++) { - expect(validateSplits(invalidSplits[i], 'test_method')).toBe(false); // It will return false as the array is of an incorrect type. - expect(loggerMock.e.mock.calls).toEqual([['test_method: split_names must be a non-empty array.']]); // Should log the error for the collection. + expect(validateSplits(loggerMock, invalidSplits[i], 'test_method')).toBe(false); // It will return false as the array is of an incorrect type. + expect(loggerMock.error.mock.calls).toEqual([['test_method: split_names must be a non-empty array.']]); // Should log the error for the collection. expect(validateSplitMock.mock.calls.length).toBe(0); // Should not try to validate any inner value if there is no valid array. - loggerMock.e.mockClear(); + loggerMock.error.mockClear(); } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. }); test('Should strip out any invalid value from the array', () => { // We use a mock function for individual validation. - validateSplitMock.mockImplementation(value => startsWith(value, 'invalid') ? false : value); + validateSplitMock.mockImplementation((_, value) => startsWith(value, 'invalid') ? false : value); const myArr = ['valid_name', 'invalid_name', 'invalid_val_2', 'something_valid']; - expect(validateSplits(myArr, 'test_method')).toEqual(['valid_name', 'something_valid']); // It will return the array without the invalid values. + expect(validateSplits(loggerMock, myArr, 'test_method')).toEqual(['valid_name', 'something_valid']); // It will return the array without the invalid values. for (let i = 0; i < myArr.length; i++) { - expect(validateSplitMock.mock.calls[i]).toEqual([myArr[i], 'test_method', 'split name']); // Should validate any inner value independently. + expect(validateSplitMock.mock.calls[i]).toEqual([loggerMock, myArr[i], 'test_method', 'split name']); // Should validate any inner value independently. } - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any error for the collection. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings for the collection. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any error for the collection. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings for the collection. }); }); diff --git a/src/utils/inputValidation/__tests__/trafficType.spec.ts b/src/utils/inputValidation/__tests__/trafficType.spec.ts index 1b7a8517..9e18d271 100644 --- a/src/utils/inputValidation/__tests__/trafficType.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficType.spec.ts @@ -36,14 +36,14 @@ const convertibleTrafficTypes = [ describe('INPUT VALIDATION for Traffic Types', () => { test('Should return the provided traffic type if it is a valid string without logging any errors', () => { - expect(validateTrafficType('traffictype', 'some_method_trafficType')).toBe('traffictype'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(validateTrafficType('traffic_type', 'some_method_trafficType')).toBe('traffic_type'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. - expect(validateTrafficType('traffic-type-23', 'some_method_trafficType')).toBe('traffic-type-23'); // It should return the provided string if it is valid. - expect(loggerMock.e.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateTrafficType(loggerMock, 'traffictype', 'some_method_trafficType')).toBe('traffictype'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateTrafficType(loggerMock, 'traffic_type', 'some_method_trafficType')).toBe('traffic_type'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(validateTrafficType(loggerMock, 'traffic-type-23', 'some_method_trafficType')).toBe('traffic-type-23'); // It should return the provided string if it is valid. + expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); @@ -52,11 +52,11 @@ describe('INPUT VALIDATION for Traffic Types', () => { for (let i = 0; i < convertibleTrafficTypes.length; i++) { const convertibleTrafficType = convertibleTrafficTypes[i]; - expect(validateTrafficType(convertibleTrafficType, 'some_method_trafficType')).toBe(convertibleTrafficType.toLowerCase()); // It should return the lowercase version of the traffic type received. - expect(loggerMock.w.mock.calls[i][0]).toEqual(`some_method_trafficType: ${errorMsgs.LOWERCASE_TRAFFIC_TYPE}`); // Should log a warning. + expect(validateTrafficType(loggerMock, convertibleTrafficType, 'some_method_trafficType')).toBe(convertibleTrafficType.toLowerCase()); // It should return the lowercase version of the traffic type received. + expect(loggerMock.warn.mock.calls[i][0]).toEqual(`some_method_trafficType: ${errorMsgs.LOWERCASE_TRAFFIC_TYPE}`); // Should log a warning. } - expect(loggerMock.e.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. mockClear(); }); @@ -66,11 +66,11 @@ describe('INPUT VALIDATION for Traffic Types', () => { const invalidValue = invalidTrafficTypes[i]['tt']; const expectedLog = invalidTrafficTypes[i]['msg']; - expect(validateTrafficType(invalidValue, 'test_method')).toBe(false); // Invalid traffic types should always return false. - expect(loggerMock.e.mock.calls[i][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid traffic type. + expect(validateTrafficType(loggerMock, invalidValue, 'test_method')).toBe(false); // Invalid traffic types should always return false. + expect(loggerMock.error.mock.calls[i][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid traffic type. } - expect(loggerMock.w.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts b/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts index 40ad0ee7..131c9b84 100644 --- a/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts @@ -37,17 +37,17 @@ describe('validateTrafficTypeExistance', () => { test('Should return true without going to the storage and log nothing if the SDK is not ready or in localhost mode', () => { // Not ready and not localstorage - expect(validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is not ready yet, it will return true. + expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is not ready yet, it will return true. expect(splitsCacheMock.trafficTypeExists.mock.calls.length).toBe(0); // If the SDK is not ready yet, it does not try to go to the storage. - expect(loggerMock.e.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. - expect(loggerMock.e.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. + expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. + expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. // Ready and in localstorage mode. readinessManagerMock.isReady.mockImplementation(() => true); - expect(validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, LOCALHOST_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is in localhost mode, it will return true. + expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, LOCALHOST_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is in localhost mode, it will return true. expect(splitsCacheMock.trafficTypeExists.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it does not try to go to the storage. - expect(loggerMock.w.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any warnings. - expect(loggerMock.e.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any errors. mockClear(); }); @@ -56,10 +56,10 @@ describe('validateTrafficTypeExistance', () => { // Ready, standalone, and the TT exists in the storage. readinessManagerMock.isReady.mockImplementation(() => true); - expect(validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_EXISTENT_TT, 'test_method')).toBe(true); // If the SDK is in condition to validate but the TT exists, it will return true. + expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_EXISTENT_TT, 'test_method')).toBe(true); // If the SDK is in condition to validate but the TT exists, it will return true. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_EXISTENT_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the storage. - expect(loggerMock.w.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any warnings. - expect(loggerMock.e.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any errors. + expect(loggerMock.warn.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any warnings. + expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any errors. mockClear(); splitsCacheMock.trafficTypeExists.mockClear(); @@ -67,10 +67,10 @@ describe('validateTrafficTypeExistance', () => { test('Should return false and log warning if SDK Ready, not localhost mode and the traffic type does NOT exist in the storage', () => { // Ready, standalone, and the TT not exists in the storage. - expect(validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_NOT_EXISTENT_TT, 'test_method_y')).toBe(false); // If the SDK is in condition to validate but the TT does not exist in the storage, it will return false. + expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_NOT_EXISTENT_TT, 'test_method_y')).toBe(false); // If the SDK is in condition to validate but the TT does not exist in the storage, it will return false. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_NOT_EXISTENT_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the storage. - expect(loggerMock.w.mock.calls).toEqual([[`test_method_y: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. - expect(loggerMock.e.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. + expect(loggerMock.warn.mock.calls).toEqual([[`test_method_y: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. + expect(loggerMock.error.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. mockClear(); splitsCacheMock.trafficTypeExists.mockClear(); @@ -79,31 +79,31 @@ describe('validateTrafficTypeExistance', () => { test('validateTrafficTypeExistance w/async storage - If the storage is async but the SDK is in condition to validate, it will validate that the TT exists on the storage', async () => { // Ready, standalone, the TT exists in the storage. - const validationPromise = validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_EXISTENT_ASYNC_TT, 'test_method_z'); + const validationPromise = validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_EXISTENT_ASYNC_TT, 'test_method_z'); expect(thenable(validationPromise)).toBe(true); // If the storage is async, it should also return a promise. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_EXISTENT_ASYNC_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the async storage. - expect(loggerMock.w.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. - expect(loggerMock.e.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.warn.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.error.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. const isValid = await validationPromise; expect(isValid).toBe(true); // As the split existed, it will resolve to true. - expect(loggerMock.w.mock.calls.length).toBe(0); // It was valid so no logs. - expect(loggerMock.e.mock.calls.length).toBe(0); // It was valid so no logs. + expect(loggerMock.warn.mock.calls.length).toBe(0); // It was valid so no logs. + expect(loggerMock.error.mock.calls.length).toBe(0); // It was valid so no logs. // Second round, a TT that does not exist on the asnyc storage splitsCacheMock.trafficTypeExists.mockClear(); - const validationPromise2 = validateTrafficTypeExistance(readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_NOT_EXISTENT_ASYNC_TT, 'test_method_z'); + const validationPromise2 = validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_NOT_EXISTENT_ASYNC_TT, 'test_method_z'); expect(thenable(validationPromise2)).toBe(true); // If the storage is async, it should also return a promise. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_NOT_EXISTENT_ASYNC_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the async storage. - expect(loggerMock.w.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. - expect(loggerMock.e.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.warn.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.error.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. const isValid2 = await validationPromise2; expect(isValid2).toBe(false); // As the split is not on the storage, it will resolve to false, failing the validation.. - expect(loggerMock.w.mock.calls).toEqual([[`test_method_z: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_ASYNC_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. - expect(loggerMock.e.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. + expect(loggerMock.warn.mock.calls).toEqual([[`test_method_z: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_ASYNC_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. + expect(loggerMock.error.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. mockClear(); splitsCacheMock.trafficTypeExists.mockClear(); diff --git a/src/utils/settingsValidation/__tests__/settings.mocks.ts b/src/utils/settingsValidation/__tests__/settings.mocks.ts index d3264707..1a7a946b 100644 --- a/src/utils/settingsValidation/__tests__/settings.mocks.ts +++ b/src/utils/settingsValidation/__tests__/settings.mocks.ts @@ -1,6 +1,6 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS'; import { ISettings } from '../../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; export const settingsWithKey = { core: { @@ -8,7 +8,8 @@ export const settingsWithKey = { }, startup: { readyTimeout: 1, - } + }, + log: loggerMock }; export const settingsWithKeyAndTT = { @@ -18,7 +19,8 @@ export const settingsWithKeyAndTT = { }, startup: { readyTimeout: 1, - } + }, + log: loggerMock }; export const settingsWithKeyObject = { @@ -30,7 +32,8 @@ export const settingsWithKeyObject = { }, startup: { readyTimeout: 1, - } + }, + log: loggerMock }; export const fullSettings: ISettings = { @@ -78,7 +81,7 @@ export const fullSettings: ISettings = { auth: 'auth', streaming: 'streaming' }, - log: noopLogger + log: loggerMock }; export const settingsSplitApi = { @@ -95,5 +98,5 @@ export const settingsSplitApi = { sync: { impressionsMode: 'DEBUG' }, - log: noopLogger -} as ISettings; + log: loggerMock +}; diff --git a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts index e3a4eed0..2acacfa0 100644 --- a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts +++ b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts @@ -18,27 +18,27 @@ describe('validateSplitFilters', () => { test('Returns default output with empty values if `splitFilters` is an invalid object or `mode` is not \'standalone\'', () => { - expect(validateSplitFilters(undefined, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(validateSplitFilters(null, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.w.mock.calls.length === 0).toBe(true); + expect(validateSplitFilters(loggerMock, undefined, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array + expect(validateSplitFilters(loggerMock, null, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array + expect(loggerMock.warn.mock.calls.length === 0).toBe(true); - expect(validateSplitFilters(true, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.w.mock.calls[0]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); + expect(validateSplitFilters(loggerMock, true, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array + expect(loggerMock.warn.mock.calls[0]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); - expect(validateSplitFilters(15, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.w.mock.calls[1]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); + expect(validateSplitFilters(loggerMock, 15, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array + expect(loggerMock.warn.mock.calls[1]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); - expect(validateSplitFilters('string', STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.w.mock.calls[2]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); + expect(validateSplitFilters(loggerMock, 'string', STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array + expect(loggerMock.warn.mock.calls[2]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); - expect(validateSplitFilters([], STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.w.mock.calls[3]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); + expect(validateSplitFilters(loggerMock, [], STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array + expect(loggerMock.warn.mock.calls[3]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); - expect(validateSplitFilters([{ type: 'byName', values: ['split_1'] }], CONSUMER_MODE)).toEqual(defaultOutput); - expect(loggerMock.w.mock.calls[4]).toEqual(["Factory instantiation: split filters have been configured but will have no effect if mode is not 'standalone', since synchronization is being deferred to an external tool."]); + expect(validateSplitFilters(loggerMock, [{ type: 'byName', values: ['split_1'] }], CONSUMER_MODE)).toEqual(defaultOutput); + expect(loggerMock.warn.mock.calls[4]).toEqual(["Factory instantiation: split filters have been configured but will have no effect if mode is not 'standalone', since synchronization is being deferred to an external tool."]); - expect(loggerMock.d.mock.calls.length === 0).toBe(true); - expect(loggerMock.e.mock.calls.length === 0).toBe(true); + expect(loggerMock.debug.mock.calls.length === 0).toBe(true); + expect(loggerMock.error.mock.calls.length === 0).toBe(true); mockClear(); }); @@ -54,9 +54,9 @@ describe('validateSplitFilters', () => { queryString: null, groupedFilters: { byName: [], byPrefix: [] } }; - expect(validateSplitFilters(splitFilters, STANDALONE_MODE)).toEqual(output); // filters without values - expect(loggerMock.d.mock.calls[0]).toEqual(["Factory instantiation: splits filtering criteria is 'null'."]); - loggerMock.d.mockClear(); + expect(validateSplitFilters(loggerMock, splitFilters, STANDALONE_MODE)).toEqual(output); // filters without values + expect(loggerMock.debug.mock.calls[0]).toEqual(["Factory instantiation: splits filtering criteria is 'null'."]); + loggerMock.debug.mockClear(); splitFilters.push( { type: 'invalid', values: [] }, @@ -64,15 +64,15 @@ describe('validateSplitFilters', () => { { type: null, values: [] }, { type: 'byName', values: [13] }); output.validFilters.push({ type: 'byName', values: [13] }); - expect(validateSplitFilters(splitFilters, STANDALONE_MODE)).toEqual(output); // some filters are invalid - expect(loggerMock.d.mock.calls).toEqual([["Factory instantiation: splits filtering criteria is 'null'."]]); - expect(loggerMock.w.mock.calls).toEqual([ + expect(validateSplitFilters(loggerMock, splitFilters, STANDALONE_MODE)).toEqual(output); // some filters are invalid + expect(loggerMock.debug.mock.calls).toEqual([["Factory instantiation: splits filtering criteria is 'null'."]]); + expect(loggerMock.warn.mock.calls).toEqual([ ["Factory instantiation: split filter at position '3' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."], // invalid value of `type` property ["Factory instantiation: split filter at position '4' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."], // invalid type of `values` property ["Factory instantiation: split filter at position '5' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."] // invalid type of `type` property ]); - expect(loggerMock.e.mock.calls).toEqual([ + expect(loggerMock.error.mock.calls).toEqual([ ['Factory instantiation: you passed an invalid byName filter value, byName filter value must be a non-empty string.'], ['Factory instantiation: byName filter must be a non-empty array.'] ]); @@ -90,11 +90,11 @@ describe('validateSplitFilters', () => { queryString: queryStrings[i], groupedFilters: groupedFilters[i] }; - expect(validateSplitFilters(splitFilters[i], STANDALONE_MODE)).toEqual(output); // splitFilters #${i} - expect(loggerMock.d.mock.calls[loggerMock.d.mock.calls.length - 1]).toEqual([`Factory instantiation: splits filtering criteria is '${queryStrings[i]}'.`]); + expect(validateSplitFilters(loggerMock, splitFilters[i], STANDALONE_MODE)).toEqual(output); // splitFilters #${i} + expect(loggerMock.debug.mock.calls[loggerMock.debug.mock.calls.length - 1]).toEqual([`Factory instantiation: splits filtering criteria is '${queryStrings[i]}'.`]); } else { // tests where validateSplitFilters throws an exception - expect(() => validateSplitFilters(splitFilters[i], STANDALONE_MODE)).toThrow(queryStrings[i]); + expect(() => validateSplitFilters(loggerMock, splitFilters[i], STANDALONE_MODE)).toThrow(queryStrings[i]); } } diff --git a/src/utils/settingsValidation/integrations/__tests__/configurable.spec.ts b/src/utils/settingsValidation/integrations/__tests__/configurable.spec.ts index 2c7252b6..a6eaa23c 100644 --- a/src/utils/settingsValidation/integrations/__tests__/configurable.spec.ts +++ b/src/utils/settingsValidation/integrations/__tests__/configurable.spec.ts @@ -1,3 +1,4 @@ +import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; import { validateConfigurableIntegrations } from '../configurable'; @@ -5,14 +6,14 @@ describe('integration validator for the configurable integrations', () => { // Check different types, since `integrations` param is defined by the user test('Returns an empty array if `integrations` is an invalid object', () => { - expect(validateConfigurableIntegrations({}, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations({ integrations: undefined }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations({ integrations: true }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations({ integrations: 123 }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations({ integrations: 'string' }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations({ integrations: {} }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations({ integrations: [] }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations({ integrations: [false, 0, Infinity, new Error(), () => { }, []] }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations(loggerMock, {}, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations(loggerMock, { integrations: undefined }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations(loggerMock, { integrations: true }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations(loggerMock, { integrations: 123 }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations(loggerMock, { integrations: 'string' }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations(loggerMock, { integrations: {} }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations(loggerMock, { integrations: [] }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations(loggerMock, { integrations: [false, 0, Infinity, new Error(), () => { }, []] }, ['INT_TYPE'])).toEqual([]); }); test('Filters invalid integrations from `integrations` array', () => { @@ -34,15 +35,15 @@ describe('integration validator for the configurable integrations', () => { }; // All integrations are removed if no `validIntegrationTypes` array is passed - expect(validateConfigurableIntegrations({ integrations: [valid, validWithOptions, invalid] })) + expect(validateConfigurableIntegrations(loggerMock, { integrations: [valid, validWithOptions, invalid] })) .toEqual([]); // Integrations that do not have the passed types are removed - expect(validateConfigurableIntegrations({ integrations: [valid, validWithOptions, otherValidWithOptions, invalid] }, ['INT1'])) + expect(validateConfigurableIntegrations(loggerMock, { integrations: [valid, validWithOptions, otherValidWithOptions, invalid] }, ['INT1'])) .toEqual([valid, validWithOptions]); // Integrations that do not have the passed types or are invalid objects are removed - expect(validateConfigurableIntegrations({ integrations: [invalid, valid, false, 0, validWithOptions, Infinity, new Error(), otherValidWithOptions, () => { }, [], invalid] }, ['INT1', 'INT2'])) + expect(validateConfigurableIntegrations(loggerMock, { integrations: [invalid, valid, false, 0, validWithOptions, Infinity, new Error(), otherValidWithOptions, () => { }, [], invalid] }, ['INT1', 'INT2'])) .toEqual([valid, validWithOptions, otherValidWithOptions]); }); }); diff --git a/src/utils/settingsValidation/integrations/__tests__/plugable.spec.ts b/src/utils/settingsValidation/integrations/__tests__/plugable.spec.ts index d8056e34..15b6b6d4 100644 --- a/src/utils/settingsValidation/integrations/__tests__/plugable.spec.ts +++ b/src/utils/settingsValidation/integrations/__tests__/plugable.spec.ts @@ -1,18 +1,18 @@ import { validatePluggableIntegrations } from '../pluggable'; - +import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; describe('integrations validator for pluggable integrations', () => { // Check different types, since `integrations` param is defined by the user test('Returns an empty array if `integrations` is an invalid object', () => { - expect(validatePluggableIntegrations({})).toEqual([]); - expect(validatePluggableIntegrations({ integrations: undefined })).toEqual([]); - expect(validatePluggableIntegrations({ integrations: true })).toEqual([]); - expect(validatePluggableIntegrations({ integrations: 123 })).toEqual([]); - expect(validatePluggableIntegrations({ integrations: 'string' })).toEqual([]); - expect(validatePluggableIntegrations({ integrations: {} })).toEqual([]); - expect(validatePluggableIntegrations({ integrations: [] })).toEqual([]); - expect(validatePluggableIntegrations({ integrations: [false, 0, Infinity, new Error(), []] })).toEqual([]); + expect(validatePluggableIntegrations(loggerMock, {})).toEqual([]); + expect(validatePluggableIntegrations(loggerMock, { integrations: undefined })).toEqual([]); + expect(validatePluggableIntegrations(loggerMock, { integrations: true })).toEqual([]); + expect(validatePluggableIntegrations(loggerMock, { integrations: 123 })).toEqual([]); + expect(validatePluggableIntegrations(loggerMock, { integrations: 'string' })).toEqual([]); + expect(validatePluggableIntegrations(loggerMock, { integrations: {} })).toEqual([]); + expect(validatePluggableIntegrations(loggerMock, { integrations: [] })).toEqual([]); + expect(validatePluggableIntegrations(loggerMock, { integrations: [false, 0, Infinity, new Error(), []] })).toEqual([]); }); test('Filters invalid integration factories from `integrations` array', () => { @@ -21,7 +21,7 @@ describe('integrations validator for pluggable integrations', () => { const invalid = { queue() { } }; // Integration factories that are invalid objects are removed - expect(validatePluggableIntegrations({ integrations: [invalid, validNoopIntFactory, false, 0, validIntFactory, Infinity, new Error(), [], invalid] })) + expect(validatePluggableIntegrations(loggerMock, { integrations: [invalid, validNoopIntFactory, false, 0, validIntFactory, Infinity, new Error(), [], invalid] })) .toEqual([validNoopIntFactory, validIntFactory]); }); diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index 7ebafbf8..df33ee90 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -1,3 +1,4 @@ +import { ILogger } from '../../../logger/types'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-settings'); @@ -10,7 +11,7 @@ * * @returns {Array} array of valid integration items. The array might be empty if `settings` object does not have valid integrations. */ -export function validateIntegrations(settings: any, integrationValidator: (integrationItem: any) => boolean, extraWarning?: string) { +export function validateIntegrations(log: ILogger, settings: any, integrationValidator: (integrationItem: any) => boolean, extraWarning?: string) { const { integrations } = settings; // If integrations is not an array or an empty array, we return an empty array (no integrations). @@ -21,7 +22,7 @@ export function validateIntegrations(settings: any, integrationValidator: (integ // Log a warning if at least one item is invalid const invalids = integrations.length - validIntegrations.length; - if (invalids) settings.log.warn(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); + if (invalids) log.warn(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); return validIntegrations; } diff --git a/src/utils/settingsValidation/integrations/configurable.ts b/src/utils/settingsValidation/integrations/configurable.ts index b48818be..29b3cc11 100644 --- a/src/utils/settingsValidation/integrations/configurable.ts +++ b/src/utils/settingsValidation/integrations/configurable.ts @@ -1,5 +1,6 @@ import { validateIntegrations } from './common'; import { isString } from '../../lang'; +import { ILogger } from '../../../logger/types'; /** * This function validates `settings.integrations` object that consists of a list of configuration items, used by the isomorphic JS SDK. @@ -9,9 +10,10 @@ import { isString } from '../../lang'; * * @returns {Array} array of valid integration items. The array might be empty if `settings` object does not have valid integrations. */ -export function validateConfigurableIntegrations(settings: any, validIntegrationTypes: string[] = []) { +export function validateConfigurableIntegrations(log: ILogger, settings: any, validIntegrationTypes: string[] = []) { return validateIntegrations( + log, settings, integration => integration && isString(integration.type) && validIntegrationTypes.indexOf(integration.type) > -1, 'Integration items must have a valid \'type\' value' diff --git a/src/utils/settingsValidation/integrations/pluggable.ts b/src/utils/settingsValidation/integrations/pluggable.ts index aaf8880c..a3012181 100644 --- a/src/utils/settingsValidation/integrations/pluggable.ts +++ b/src/utils/settingsValidation/integrations/pluggable.ts @@ -1,5 +1,6 @@ import { ISettings } from '../../../types'; import { validateIntegrations } from './common'; +import { ILogger } from '../../../logger/types'; /** * This function validates `settings.integrations` object that consists of a list of pluggable integration factories. @@ -8,9 +9,10 @@ import { validateIntegrations } from './common'; * * @returns {Array} array of valid integration factories. The array might be empty if `settings` object does not have valid integrations. */ -export function validatePluggableIntegrations(settings: any): ISettings['integrations'] { +export function validatePluggableIntegrations(log: ILogger, settings: any): ISettings['integrations'] { return validateIntegrations( + log, settings, integration => typeof integration === 'function', 'Integration items must be functions that initialize the integrations' diff --git a/src/utils/settingsValidation/storage/__tests__/storageCS.spec.ts b/src/utils/settingsValidation/storage/__tests__/storageCS.spec.ts index a8dcd3e4..0647d7cd 100644 --- a/src/utils/settingsValidation/storage/__tests__/storageCS.spec.ts +++ b/src/utils/settingsValidation/storage/__tests__/storageCS.spec.ts @@ -1,20 +1,21 @@ import { validateStorageCS } from '../storageCS'; import { InMemoryStorageCSFactory } from '../../../../storages/inMemory/InMemoryStorageCS'; +import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; describe('storage validator for pluggable storage (client-side)', () => { // Check different types, since `storage` param is defined by the user test('fallbacks to default InMemory storage if the storage is invalid or not provided', () => { - expect(validateStorageCS({})).toBe(InMemoryStorageCSFactory); - expect(validateStorageCS({ storage: undefined })).toBe(InMemoryStorageCSFactory); - expect(validateStorageCS({ storage: {} })).toBe(InMemoryStorageCSFactory); - expect(validateStorageCS({ storage: 'invalid storage' })).toBe(InMemoryStorageCSFactory); + expect(validateStorageCS(loggerMock, {})).toBe(InMemoryStorageCSFactory); + expect(validateStorageCS(loggerMock, { storage: undefined })).toBe(InMemoryStorageCSFactory); + expect(validateStorageCS(loggerMock, { storage: {} })).toBe(InMemoryStorageCSFactory); + expect(validateStorageCS(loggerMock, { storage: 'invalid storage' })).toBe(InMemoryStorageCSFactory); }); test('returns the provided storage factory if it is valid', () => { const mockStorageFactory = () => {}; - expect(validateStorageCS({ storage: mockStorageFactory })).toBe(mockStorageFactory); + expect(validateStorageCS(loggerMock, { storage: mockStorageFactory })).toBe(mockStorageFactory); }); }); diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index f5300b9f..674a21f9 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -1,5 +1,6 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS'; import { ISettings } from '../../../types'; +import { ILogger } from '../../../logger/types'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-settings'); @@ -10,14 +11,14 @@ import { ISettings } from '../../../types'; * * @returns {Object} valid storage factory. It might be the default `InMemoryStorageCSFactory` if the provided storage is invalid. */ -export function validateStorageCS(settings: any): ISettings['storage'] { +export function validateStorageCS(log: ILogger, settings: any): ISettings['storage'] { const { storage } = settings; // validate storage // @TODO validate its API (Splits cache, MySegments cache, etc) when supporting custom storages if (storage) { if (typeof storage === 'function') return storage; - settings.log.warn('The provided storage is invalid. Fallbacking into default MEMORY storage'); + log.warn('The provided storage is invalid. Fallbacking into default MEMORY storage'); } // return default InMemory storage if provided one is not valid From b93e2f7471f0d47331ad3b519b0cc20160ccea20 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 3 Mar 2021 18:19:48 -0300 Subject: [PATCH 09/58] removed noopLogger --- .../__tests__/evaluate-feature.spec.ts | 22 ++--- .../__tests__/evaluate-features.spec.ts | 6 +- src/evaluator/combiners/__tests__/and.spec.ts | 6 +- .../combiners/__tests__/ifelseif.spec.ts | 8 +- src/evaluator/matchers/__tests__/all.spec.ts | 4 +- .../matchers/__tests__/between.spec.ts | 4 +- .../matchers/__tests__/boolean.spec.ts | 4 +- .../matchers/__tests__/cont_all.spec.ts | 4 +- .../matchers/__tests__/cont_any.spec.ts | 4 +- .../matchers/__tests__/cont_str.spec.ts | 4 +- .../matchers/__tests__/dependency.spec.ts | 24 ++--- src/evaluator/matchers/__tests__/eq.spec.ts | 4 +- .../matchers/__tests__/eq_set.spec.ts | 4 +- src/evaluator/matchers/__tests__/ew.spec.ts | 6 +- src/evaluator/matchers/__tests__/gte.spec.ts | 4 +- src/evaluator/matchers/__tests__/lte.spec.ts | 4 +- .../matchers/__tests__/part_of.spec.ts | 4 +- .../matchers/__tests__/regex.spec.ts | 8 +- .../__tests__/segment/client_side.spec.ts | 6 +- .../__tests__/segment/server_side.spec.ts | 4 +- src/evaluator/matchers/__tests__/sw.spec.ts | 4 +- .../matchers/__tests__/whitelist.spec.ts | 4 +- .../parser/__tests__/boolean.spec.ts | 4 +- src/evaluator/parser/__tests__/index.spec.ts | 36 ++++---- .../parser/__tests__/invalidMatcher.spec.ts | 8 +- src/evaluator/parser/__tests__/regex.spec.ts | 4 +- src/evaluator/parser/__tests__/set.spec.ts | 88 +++++++++---------- src/evaluator/parser/__tests__/string.spec.ts | 76 ++++++++-------- .../__tests__/trafficAllocation.spec.ts | 10 +-- src/logger/noopLogger.ts | 8 -- .../__tests__/SplitsCacheInLocal.spec.ts | 12 +-- 31 files changed, 190 insertions(+), 198 deletions(-) delete mode 100644 src/logger/noopLogger.ts diff --git a/src/evaluator/__tests__/evaluate-feature.spec.ts b/src/evaluator/__tests__/evaluate-feature.spec.ts index f4a9de8b..fdfdd94e 100644 --- a/src/evaluator/__tests__/evaluate-feature.spec.ts +++ b/src/evaluator/__tests__/evaluate-feature.spec.ts @@ -1,7 +1,7 @@ // @ts-nocheck import { evaluateFeature } from '../index'; import * as LabelsConstants from '../../utils/labels'; -import { noopLogger } from '../../logger/noopLogger'; +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; const splitsMock = { regular: '{"changeNumber":1487277320548,"trafficAllocationSeed":1667452163,"trafficAllocation":100,"trafficTypeName":"user","name":"always-on","seed":1684183541,"configurations":{},"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"conditionType":"ROLLOUT","matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}', @@ -36,7 +36,7 @@ test('EVALUATOR / should return label exception, treatment control and config nu 'throw_exception', null, mockStorage, - noopLogger + loggerMock ); // This validation is async because the only exception possible when retrieving a Split would happen with Async storages. @@ -60,7 +60,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'config', null, mockStorage, - noopLogger + loggerMock ); expect(evaluationWithConfig).toEqual(expectedOutput); // If the split is retrieved successfully we should get the right evaluation result, label and config. @@ -69,7 +69,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'not_existent_split', null, mockStorage, - noopLogger + loggerMock ); expect(evaluationNotFound).toEqual(expectedOutputControl); // If the split is not retrieved successfully because it does not exist, we should get the right evaluation result, label and config. @@ -78,7 +78,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'regular', null, mockStorage, - noopLogger + loggerMock ); expect(evaluation).toEqual({ ...expectedOutput, config: null }); // If the split is retrieved successfully we should get the right evaluation result, label and config. If Split has no config it should have config equal null. @@ -87,7 +87,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'killed', null, mockStorage, - noopLogger + loggerMock ); expect(evaluationKilled).toEqual({ ...expectedOutput, treatment: 'off', config: null, label: LabelsConstants.SPLIT_KILLED }); // If the split is retrieved but is killed, we should get the right evaluation result, label and config. @@ -97,7 +97,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'archived', null, mockStorage, - noopLogger + loggerMock ); expect(evaluationArchived).toEqual({ ...expectedOutput, treatment: 'control', label: LabelsConstants.SPLIT_ARCHIVED, config: null }); // If the split is retrieved but is archived, we should get the right evaluation result, label and config. @@ -107,7 +107,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'trafficAlocation1', null, mockStorage, - noopLogger + loggerMock ); expect(evaluationtrafficAlocation1).toEqual({ ...expectedOutput, label: LabelsConstants.NOT_IN_SPLIT, config: null, treatment: 'off' }); // If the split is retrieved but is not in split (out of Traffic Allocation), we should get the right evaluation result, label and config. @@ -117,7 +117,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'killedWithConfig', null, mockStorage, - noopLogger + loggerMock ); expect(evaluationKilledWithConfig).toEqual({ ...expectedOutput, treatment: 'off', label: LabelsConstants.SPLIT_KILLED }); // If the split is retrieved but is killed, we should get the right evaluation result, label and config. @@ -127,7 +127,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'archivedWithConfig', null, mockStorage, - noopLogger + loggerMock ); expect(evaluationArchivedWithConfig).toEqual({ ...expectedOutput, treatment: 'control', label: LabelsConstants.SPLIT_ARCHIVED, config: null }); // If the split is retrieved but is archived, we should get the right evaluation result, label and config. @@ -137,7 +137,7 @@ test('EVALUATOR / should return right label, treatment and config if storage ret 'trafficAlocation1WithConfig', null, mockStorage, - noopLogger + loggerMock ); expect(evaluationtrafficAlocation1WithConfig).toEqual({ ...expectedOutput, label: LabelsConstants.NOT_IN_SPLIT, treatment: 'off' }); // If the split is retrieved but is not in split (out of Traffic Allocation), we should get the right evaluation result, label and config. diff --git a/src/evaluator/__tests__/evaluate-features.spec.ts b/src/evaluator/__tests__/evaluate-features.spec.ts index 6ecd2f22..2b3cddb6 100644 --- a/src/evaluator/__tests__/evaluate-features.spec.ts +++ b/src/evaluator/__tests__/evaluate-features.spec.ts @@ -1,7 +1,7 @@ // @ts-nocheck import { evaluateFeatures } from '../index'; import * as LabelsConstants from '../../utils/labels'; -import { noopLogger } from '../../logger/noopLogger'; +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; const splitsMock = { regular: '{"changeNumber":1487277320548,"trafficAllocationSeed":1667452163,"trafficAllocation":100,"trafficTypeName":"user","name":"always-on","seed":1684183541,"configurations":{},"status":"ACTIVE","killed":false,"defaultTreatment":"off","conditions":[{"conditionType":"ROLLOUT","matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":""},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":{"segmentName":""},"unaryNumericMatcherData":{"dataType":"","value":0},"whitelistMatcherData":{"whitelist":null},"betweenMatcherData":{"dataType":"","start":0,"end":0}}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}', @@ -48,7 +48,7 @@ test('EVALUATOR - Multiple evaluations at once / should return label exception, ['throw_exception'], null, mockStorage, - noopLogger + loggerMock ); expect(evaluation).toEqual(expectedOutput); // If there was an error on the `getSplits` we should get the results for exception. @@ -72,7 +72,7 @@ test('EVALUATOR - Multiple evaluations at once / should return right labels, tre ['config', 'not_existent_split', 'regular', 'killed', 'archived', 'trafficAlocation1', 'killedWithConfig', 'archivedWithConfig', 'trafficAlocation1WithConfig'], null, mockStorage, - noopLogger + loggerMock ); // assert evaluationWithConfig expect(multipleEvaluationAtOnce['config']).toEqual(expectedOutput['config']); // If the split is retrieved successfully we should get the right evaluation result, label and config. diff --git a/src/evaluator/combiners/__tests__/and.spec.ts b/src/evaluator/combiners/__tests__/and.spec.ts index 0405499e..3f71c016 100644 --- a/src/evaluator/combiners/__tests__/and.spec.ts +++ b/src/evaluator/combiners/__tests__/and.spec.ts @@ -1,16 +1,16 @@ import andCombiner from '../and'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('COMBINER AND / should always return true', async function () { - let AND = andCombiner([() => true, () => true, () => true], noopLogger); + let AND = andCombiner([() => true, () => true, () => true], loggerMock); expect(await AND('always true')).toBe(true); // should always return true }); test('COMBINER AND / should always return false', async function () { - let AND = andCombiner([() => true, () => true, () => false], noopLogger); + let AND = andCombiner([() => true, () => true, () => false], loggerMock); expect(await AND('always false')).toBe(false); // should always return false }); diff --git a/src/evaluator/combiners/__tests__/ifelseif.spec.ts b/src/evaluator/combiners/__tests__/ifelseif.spec.ts index ef49c134..dba32cfd 100644 --- a/src/evaluator/combiners/__tests__/ifelseif.spec.ts +++ b/src/evaluator/combiners/__tests__/ifelseif.spec.ts @@ -1,6 +1,6 @@ // @ts-nocheck import ifElseIfCombinerFactory from '../ifelseif'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('IF ELSE IF COMBINER / should correctly propagate context parameters and predicates returns value', async function () { let inputKey = 'sample'; @@ -17,7 +17,7 @@ test('IF ELSE IF COMBINER / should correctly propagate context parameters and pr } let predicates = [evaluator]; - let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, noopLogger); + let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, loggerMock); expect(await ifElseIfEvaluator(inputKey, inputSeed, inputAttributes) === evaluationResult).toBe(true); console.log(`evaluator should return ${evaluationResult}`); @@ -36,7 +36,7 @@ test('IF ELSE IF COMBINER / should stop evaluating when one matcher return a tre } ]; - let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, noopLogger); + let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, loggerMock); expect(await ifElseIfEvaluator()).toBe('exclude'); // exclude treatment found }); @@ -54,7 +54,7 @@ test('IF ELSE IF COMBINER / should return undefined if there is none matching ru } ]; - const ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, noopLogger); + const ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, loggerMock); expect(await ifElseIfEvaluator() === undefined).toBe(true); }); diff --git a/src/evaluator/matchers/__tests__/all.spec.ts b/src/evaluator/matchers/__tests__/all.spec.ts index b2d8b54e..d4a47b09 100644 --- a/src/evaluator/matchers/__tests__/all.spec.ts +++ b/src/evaluator/matchers/__tests__/all.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER ALL_KEYS / should always return true', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { type: matcherTypes.ALL_KEYS, value: undefined } as IMatcherDto) as IMatcher; diff --git a/src/evaluator/matchers/__tests__/between.spec.ts b/src/evaluator/matchers/__tests__/between.spec.ts index d379b035..ca95ba16 100644 --- a/src/evaluator/matchers/__tests__/between.spec.ts +++ b/src/evaluator/matchers/__tests__/between.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER BETWEEN / should return true ONLY when the value is between 10 and 20', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.BETWEEN, value: { diff --git a/src/evaluator/matchers/__tests__/boolean.spec.ts b/src/evaluator/matchers/__tests__/boolean.spec.ts index 16664423..515b46d5 100644 --- a/src/evaluator/matchers/__tests__/boolean.spec.ts +++ b/src/evaluator/matchers/__tests__/boolean.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER BOOLEAN / should return true ONLY when the value is true', function () { // @ts-ignore - const matcher = matcherFactory(noopLogger, { + const matcher = matcherFactory(loggerMock, { type: matcherTypes.EQUAL_TO_BOOLEAN, value: true } as IMatcherDto) as IMatcher; diff --git a/src/evaluator/matchers/__tests__/cont_all.spec.ts b/src/evaluator/matchers/__tests__/cont_all.spec.ts index 4f72cec1..8ea23697 100644 --- a/src/evaluator/matchers/__tests__/cont_all.spec.ts +++ b/src/evaluator/matchers/__tests__/cont_all.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER CONTAINS_ALL_OF_SET / should return true ONLY when value contains all of set ["update", "add"]', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.CONTAINS_ALL_OF_SET, value: ['update', 'add'] diff --git a/src/evaluator/matchers/__tests__/cont_any.spec.ts b/src/evaluator/matchers/__tests__/cont_any.spec.ts index 257d153a..13896900 100644 --- a/src/evaluator/matchers/__tests__/cont_any.spec.ts +++ b/src/evaluator/matchers/__tests__/cont_any.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER CONTAINS_ANY_OF_SET / should return true ONLY when value contains any of set ["update", "add"]', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.CONTAINS_ANY_OF_SET, value: ['update', 'add'] diff --git a/src/evaluator/matchers/__tests__/cont_str.spec.ts b/src/evaluator/matchers/__tests__/cont_str.spec.ts index b365d5d2..f8c56d4e 100644 --- a/src/evaluator/matchers/__tests__/cont_str.spec.ts +++ b/src/evaluator/matchers/__tests__/cont_str.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER CONTAINS_STRING / should return true ONLY when the value is contained in ["roni", "bad", "ar"]', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.CONTAINS_STRING, value: ['roni', 'bad', 'ar'] diff --git a/src/evaluator/matchers/__tests__/dependency.spec.ts b/src/evaluator/matchers/__tests__/dependency.spec.ts index f90ce7f8..6f4f62ec 100644 --- a/src/evaluator/matchers/__tests__/dependency.spec.ts +++ b/src/evaluator/matchers/__tests__/dependency.spec.ts @@ -3,7 +3,7 @@ import matcherFactory from '..'; import { evaluateFeature } from '../../index'; import { IMatcher, IMatcherDto } from '../../types'; import { IStorageSync } from '../../../storages/types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; const ALWAYS_ON_SPLIT = '{"trafficTypeName":"user","name":"always-on","trafficAllocation":100,"trafficAllocationSeed":1012950810,"seed":-725161385,"status":"ACTIVE","killed":false,"defaultTreatment":"off","changeNumber":1494364996459,"algo":2,"conditions":[{"conditionType":"ROLLOUT","matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":null},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":null,"whitelistMatcherData":null,"unaryNumericMatcherData":null,"betweenMatcherData":null}]},"partitions":[{"treatment":"on","size":100},{"treatment":"off","size":0}],"label":"in segment all"}]}'; const ALWAYS_OFF_SPLIT = '{"trafficTypeName":"user","name":"always-off","trafficAllocation":100,"trafficAllocationSeed":-331690370,"seed":403891040,"status":"ACTIVE","killed":false,"defaultTreatment":"on","changeNumber":1494365020316,"algo":2,"conditions":[{"conditionType":"ROLLOUT","matcherGroup":{"combiner":"AND","matchers":[{"keySelector":{"trafficType":"user","attribute":null},"matcherType":"ALL_KEYS","negate":false,"userDefinedSegmentMatcherData":null,"whitelistMatcherData":null,"unaryNumericMatcherData":null,"betweenMatcherData":null}]},"partitions":[{"treatment":"on","size":0},{"treatment":"off","size":100}],"label":"in segment all"}]}'; @@ -19,7 +19,7 @@ const mockStorage = { }; test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split returns one of the expected treatments', function () { - const matcherTrueAlwaysOn = matcherFactory(noopLogger, { + const matcherTrueAlwaysOn = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', @@ -27,7 +27,7 @@ test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split ret } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherFalseAlwaysOn = matcherFactory(noopLogger, { + const matcherFalseAlwaysOn = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', @@ -35,7 +35,7 @@ test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split ret } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherTrueAlwaysOff = matcherFactory(noopLogger, { + const matcherTrueAlwaysOff = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-off', @@ -43,7 +43,7 @@ test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split ret } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherFalseAlwaysOff = matcherFactory(noopLogger, { + const matcherFalseAlwaysOff = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-off', @@ -58,7 +58,7 @@ test('MATCHER IN_SPLIT_TREATMENT / should return true ONLY when parent split ret }); test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { - const matcherParentNotExist = matcherFactory(noopLogger, { + const matcherParentNotExist = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'not-existent-split', @@ -67,7 +67,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; // @ts-ignore - const matcherNoTreatmentsExpected = matcherFactory(noopLogger, { + const matcherNoTreatmentsExpected = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', @@ -76,7 +76,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; // @ts-ignore - const matcherParentNameEmpty = matcherFactory(noopLogger, { + const matcherParentNameEmpty = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: '', @@ -85,7 +85,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; // @ts-ignore - const matcherParentNameWrongType = matcherFactory(noopLogger, { + const matcherParentNameWrongType = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: { some: 44 }, @@ -93,7 +93,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherExpectedTreatmentWrongTypeMatching = matcherFactory(noopLogger, { + const matcherExpectedTreatmentWrongTypeMatching = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', @@ -101,7 +101,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; - const matcherExpectedTreatmentWrongTypeNotMatching = matcherFactory(noopLogger, { + const matcherExpectedTreatmentWrongTypeNotMatching = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-off', @@ -111,7 +111,7 @@ test('MATCHER IN_SPLIT_TREATMENT / Edge cases', function () { } as IMatcherDto, mockStorage as IStorageSync) as IMatcher; // @ts-ignore - const matcherExpectationsListWrongType = matcherFactory(noopLogger, { + const matcherExpectationsListWrongType = matcherFactory(loggerMock, { type: matcherTypes.IN_SPLIT_TREATMENT, value: { split: 'always-on', diff --git a/src/evaluator/matchers/__tests__/eq.spec.ts b/src/evaluator/matchers/__tests__/eq.spec.ts index d2d03395..40b40f8d 100644 --- a/src/evaluator/matchers/__tests__/eq.spec.ts +++ b/src/evaluator/matchers/__tests__/eq.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER EQUAL / should return true ONLY when the value is equal to 10', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.EQUAL_TO, value: 10 diff --git a/src/evaluator/matchers/__tests__/eq_set.spec.ts b/src/evaluator/matchers/__tests__/eq_set.spec.ts index ab713024..17450cf6 100644 --- a/src/evaluator/matchers/__tests__/eq_set.spec.ts +++ b/src/evaluator/matchers/__tests__/eq_set.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER EQUAL_TO_SET / should return true ONLY when value is equal to set ["update", "add"]', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.EQUAL_TO_SET, value: ['update', 'add'] diff --git a/src/evaluator/matchers/__tests__/ew.spec.ts b/src/evaluator/matchers/__tests__/ew.spec.ts index db8fc07f..aeb9eb0a 100644 --- a/src/evaluator/matchers/__tests__/ew.spec.ts +++ b/src/evaluator/matchers/__tests__/ew.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER ENDS_WITH / should return true ONLY when the value ends with ["a", "b", "c"]', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.ENDS_WITH, value: ['a', 'b', 'c'] @@ -20,7 +20,7 @@ test('MATCHER ENDS_WITH / should return true ONLY when the value ends with ["a", test('MATCHER ENDS_WITH / should return true ONLY when the value ends with ["demo.test.org"]', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.ENDS_WITH, value: ['demo.test.org'] diff --git a/src/evaluator/matchers/__tests__/gte.spec.ts b/src/evaluator/matchers/__tests__/gte.spec.ts index c65c3ed1..f7a4ec54 100644 --- a/src/evaluator/matchers/__tests__/gte.spec.ts +++ b/src/evaluator/matchers/__tests__/gte.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER GREATER THAN OR EQUAL / should return true ONLY when the value is greater than or equal to 10', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.GREATER_THAN_OR_EQUAL_TO, value: 10 diff --git a/src/evaluator/matchers/__tests__/lte.spec.ts b/src/evaluator/matchers/__tests__/lte.spec.ts index addffbf0..ad920020 100644 --- a/src/evaluator/matchers/__tests__/lte.spec.ts +++ b/src/evaluator/matchers/__tests__/lte.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER LESS THAN OR EQUAL / should return true ONLY when the value is less than or equal to 10', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.LESS_THAN_OR_EQUAL_TO, value: 10 diff --git a/src/evaluator/matchers/__tests__/part_of.spec.ts b/src/evaluator/matchers/__tests__/part_of.spec.ts index 6cfcb53f..9472d389 100644 --- a/src/evaluator/matchers/__tests__/part_of.spec.ts +++ b/src/evaluator/matchers/__tests__/part_of.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER PART_OF_SET / should return true ONLY when value is part of of set ["update", "add", "delete"]', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.PART_OF_SET, value: ['update', 'add', 'delete'] diff --git a/src/evaluator/matchers/__tests__/regex.spec.ts b/src/evaluator/matchers/__tests__/regex.spec.ts index 3ce1e1f3..3465d623 100644 --- a/src/evaluator/matchers/__tests__/regex.spec.ts +++ b/src/evaluator/matchers/__tests__/regex.spec.ts @@ -3,11 +3,11 @@ import matcherFactory from '..'; import fs from 'fs'; import rl from 'readline'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER REGEX (STRING) / should match the attribute value only with the string starts with hello', function () { // @ts-ignore - const matcher = matcherFactory(noopLogger, { + const matcher = matcherFactory(loggerMock, { type: matcherTypes.MATCHES_STRING, value: '^hello' } as IMatcherDto) as IMatcher; @@ -18,7 +18,7 @@ test('MATCHER REGEX (STRING) / should match the attribute value only with the st test('MATCHER REGEX (STRING) / incorrectly matches unicode characters', function () { // @ts-ignore - const matcher = matcherFactory(noopLogger, { + const matcher = matcherFactory(loggerMock, { type: matcherTypes.MATCHES_STRING, value: 'a.b' } as IMatcherDto) as IMatcher; @@ -47,7 +47,7 @@ test('MATCHER REGEX (STRING) / incorrectly matches unicode characters', function const isTestTrue = test === 'true'; // @ts-ignore - const matcher = matcherFactory(noopLogger, { + const matcher = matcherFactory(loggerMock, { type: matcherTypes.MATCHES_STRING, value: regex } as IMatcherDto) as IMatcher; diff --git a/src/evaluator/matchers/__tests__/segment/client_side.spec.ts b/src/evaluator/matchers/__tests__/segment/client_side.spec.ts index 66941ed8..7514a862 100644 --- a/src/evaluator/matchers/__tests__/segment/client_side.spec.ts +++ b/src/evaluator/matchers/__tests__/segment/client_side.spec.ts @@ -2,12 +2,12 @@ import { matcherTypes } from '../../matcherTypes'; import matcherFactory from '../..'; import { IMatcher, IMatcherDto } from '../../../types'; import { IStorageSync } from '../../../../storages/types'; -import { noopLogger } from '../../../../logger/noopLogger'; +import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; test('MATCHER IN_SEGMENT / should return true ONLY when the segment is defined inside the segment storage', async function () { const segment = 'employees'; - const matcherTrue = matcherFactory(noopLogger, { + const matcherTrue = matcherFactory(loggerMock, { type: matcherTypes.IN_SEGMENT, value: segment } as IMatcherDto, { @@ -18,7 +18,7 @@ test('MATCHER IN_SEGMENT / should return true ONLY when the segment is defined i } } as IStorageSync) as IMatcher; - const matcherFalse = matcherFactory(noopLogger, { + const matcherFalse = matcherFactory(loggerMock, { type: matcherTypes.IN_SEGMENT, value: segment + 'asd' } as IMatcherDto, { diff --git a/src/evaluator/matchers/__tests__/segment/server_side.spec.ts b/src/evaluator/matchers/__tests__/segment/server_side.spec.ts index b056608b..97d9dcc7 100644 --- a/src/evaluator/matchers/__tests__/segment/server_side.spec.ts +++ b/src/evaluator/matchers/__tests__/segment/server_side.spec.ts @@ -2,12 +2,12 @@ import { matcherTypes } from '../../matcherTypes'; import matcherFactory from '../..'; import { IMatcher, IMatcherDto } from '../../../types'; import { IStorageSync } from '../../../../storages/types'; -import { noopLogger } from '../../../../logger/noopLogger'; +import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; test('MATCHER IN_SEGMENT / should return true ONLY when the key is defined inside the segment', async function () { const segment = 'employees'; - const matcher = matcherFactory(noopLogger, { + const matcher = matcherFactory(loggerMock, { type: matcherTypes.IN_SEGMENT, value: segment } as IMatcherDto, { diff --git a/src/evaluator/matchers/__tests__/sw.spec.ts b/src/evaluator/matchers/__tests__/sw.spec.ts index dd282b0d..312ae8b1 100644 --- a/src/evaluator/matchers/__tests__/sw.spec.ts +++ b/src/evaluator/matchers/__tests__/sw.spec.ts @@ -1,11 +1,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER STARTS_WITH / should return true ONLY when the value starts with ["a", "b", "c"]', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { negate: false, type: matcherTypes.STARTS_WITH, value: ['a', 'b', 'c'] diff --git a/src/evaluator/matchers/__tests__/whitelist.spec.ts b/src/evaluator/matchers/__tests__/whitelist.spec.ts index a2e43420..4c7aa723 100644 --- a/src/evaluator/matchers/__tests__/whitelist.spec.ts +++ b/src/evaluator/matchers/__tests__/whitelist.spec.ts @@ -2,11 +2,11 @@ import { matcherTypes } from '../matcherTypes'; import matcherFactory from '..'; import { _Set } from '../../../utils/lang/sets'; import { IMatcher, IMatcherDto } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('MATCHER WHITELIST / should return true ONLY when the key is defined', function () { // @ts-ignore - let matcher = matcherFactory(noopLogger, { + let matcher = matcherFactory(loggerMock, { type: matcherTypes.WHITELIST, value: new _Set().add('key') } as IMatcherDto) as IMatcher; diff --git a/src/evaluator/parser/__tests__/boolean.spec.ts b/src/evaluator/parser/__tests__/boolean.spec.ts index 116c3f70..81f8a30b 100644 --- a/src/evaluator/parser/__tests__/boolean.spec.ts +++ b/src/evaluator/parser/__tests__/boolean.spec.ts @@ -2,12 +2,12 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; import { IEvaluation } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('PARSER / if user.boolean is true then split 100%:on', async function () { // @ts-ignore - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/index.spec.ts b/src/evaluator/parser/__tests__/index.spec.ts index d2e218d1..a27fecc7 100644 --- a/src/evaluator/parser/__tests__/index.spec.ts +++ b/src/evaluator/parser/__tests__/index.spec.ts @@ -3,11 +3,11 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; import { bucket } from '../../../utils/murmur3/murmur3'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('PARSER / if user is in segment all 100%:on', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -33,7 +33,7 @@ test('PARSER / if user is in segment all 100%:on', async function () { test('PARSER / if user is in segment all 100%:off', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -61,7 +61,7 @@ test('PARSER / if user is in segment all 100%:off', async function () { test('PARSER / NEGATED if user is in segment all 100%:on, then no match', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -86,7 +86,7 @@ test('PARSER / NEGATED if user is in segment all 100%:on, then no match', async test('PARSER / if user is in segment ["u1", "u2", "u3", "u4"] then split 100%:on', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -125,7 +125,7 @@ test('PARSER / if user is in segment ["u1", "u2", "u3", "u4"] then split 100%:on test('PARSER / NEGATED if user is in segment ["u1", "u2", "u3", "u4"] then split 100%:on, negated results', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -164,7 +164,7 @@ test('PARSER / NEGATED if user is in segment ["u1", "u2", "u3", "u4"] then split test('PARSER / if user.account is in list ["v1", "v2", "v3"] then split 100:on', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -210,7 +210,7 @@ test('PARSER / if user.account is in list ["v1", "v2", "v3"] then split 100:on', test('PARSER / NEGATED if user.account is in list ["v1", "v2", "v3"] then split 100:on, negated results', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -256,7 +256,7 @@ test('PARSER / NEGATED if user.account is in list ["v1", "v2", "v3"] then split }); test('PARSER / if user.account is in segment all then split 100:on', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -282,7 +282,7 @@ test('PARSER / if user.account is in segment all then split 100:on', async funct test('PARSER / if user.attr is between 10 and 20 then split 100:on', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -323,7 +323,7 @@ test('PARSER / if user.attr is between 10 and 20 then split 100:on', async funct test('PARSER / NEGATED if user.attr is between 10 and 20 then split 100:on, negated results', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -365,7 +365,7 @@ test('PARSER / NEGATED if user.attr is between 10 and 20 then split 100:on, nega test('PARSER / if user.attr <= datetime 1458240947021 then split 100:on', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -410,7 +410,7 @@ test('PARSER / if user.attr <= datetime 1458240947021 then split 100:on', async test('PARSER / NEGATED if user.attr <= datetime 1458240947021 then split 100:on, negated results', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -456,7 +456,7 @@ test('PARSER / NEGATED if user.attr <= datetime 1458240947021 then split 100:on, test('PARSER / if user.attr >= datetime 1458240947021 then split 100:on', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -501,7 +501,7 @@ test('PARSER / if user.attr >= datetime 1458240947021 then split 100:on', async test('PARSER / NEGATED if user.attr >= datetime 1458240947021 then split 100:on, negated results', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -547,7 +547,7 @@ test('PARSER / NEGATED if user.attr >= datetime 1458240947021 then split 100:on, test('PARSER / if user.attr = datetime 1458240947021 then split 100:on', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -592,7 +592,7 @@ test('PARSER / if user.attr = datetime 1458240947021 then split 100:on', async f test('PARSER / NEGATED if user.attr = datetime 1458240947021 then split 100:on, negated results', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -637,7 +637,7 @@ test('PARSER / NEGATED if user.attr = datetime 1458240947021 then split 100:on, }); test('PARSER / if user is in segment all then split 20%:A,20%:B,60%:A', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/invalidMatcher.spec.ts b/src/evaluator/parser/__tests__/invalidMatcher.spec.ts index 0f724461..3ff988bd 100644 --- a/src/evaluator/parser/__tests__/invalidMatcher.spec.ts +++ b/src/evaluator/parser/__tests__/invalidMatcher.spec.ts @@ -1,10 +1,10 @@ // @ts-nocheck import parser from '..'; import { ISplitCondition } from '../../../dtos/types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('PARSER / handle invalid matcher as control', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -33,7 +33,7 @@ test('PARSER / handle invalid matcher as control', async function () { }); test('PARSER / handle invalid matcher as control (complex example)', async function () { - const evaluator = parser(noopLogger, [ + const evaluator = parser(loggerMock, [ { 'conditionType': 'WHITELIST', 'matcherGroup': { @@ -133,7 +133,7 @@ test('PARSER / handle invalid matcher as control (complex example)', async funct }); test('PARSER / handle invalid matcher as control (complex example mixing invalid and valid matchers)', async function () { - const evaluator = parser(noopLogger, [ + const evaluator = parser(loggerMock, [ { 'conditionType': 'WHITELIST', 'matcherGroup': { diff --git a/src/evaluator/parser/__tests__/regex.spec.ts b/src/evaluator/parser/__tests__/regex.spec.ts index a724f1bf..ee2b0904 100644 --- a/src/evaluator/parser/__tests__/regex.spec.ts +++ b/src/evaluator/parser/__tests__/regex.spec.ts @@ -2,11 +2,11 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; import { IEvaluation } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('PARSER / if user.string is true then split 100%:on', async function () { // @ts-ignore - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/set.spec.ts b/src/evaluator/parser/__tests__/set.spec.ts index 2200a92f..de652ed3 100644 --- a/src/evaluator/parser/__tests__/set.spec.ts +++ b/src/evaluator/parser/__tests__/set.spec.ts @@ -2,14 +2,14 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; // // EQUAL_TO_SET // test('PARSER / if user.permissions ["read", "write"] equal to set ["read", "write"] then split 100:on', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -44,7 +44,7 @@ test('PARSER / if user.permissions ["read", "write"] equal to set ["read", "writ test('PARSER / if user.permissions ["write", "read"] equal to set ["read", "write"] then split 100:on', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -79,7 +79,7 @@ test('PARSER / if user.permissions ["write", "read"] equal to set ["read", "writ test('PARSER / if user.permissions ["1", 2] equal to set ["1", "2"] then split 100:on', async function () { const label = 'permissions = ["1", "2"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -114,7 +114,7 @@ test('PARSER / if user.permissions ["1", 2] equal to set ["1", "2"] then split 1 test('PARSER / if user.permissions ["read", "write", "delete"] equal to set ["read", "write"] then not match', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -148,7 +148,7 @@ test('PARSER / if user.permissions ["read", "write", "delete"] equal to set ["re test('PARSER / if user.permissions ["read"] equal to set ["read", "write"] then not match', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -182,7 +182,7 @@ test('PARSER / if user.permissions ["read"] equal to set ["read", "write"] then test('PARSER / if user.permissions ["read", "delete"] equal to set ["read", "write"] then not match', async function () { const label = 'permissions = ["read", "write"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -216,7 +216,7 @@ test('PARSER / if user.permissions ["read", "delete"] equal to set ["read", "wri test('PARSER / if user.countries ["argentina", "usa"] equal to set ["usa","argentina"] then split 100:on', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -250,7 +250,7 @@ test('PARSER / if user.countries ["argentina", "usa"] equal to set ["usa","argen test('PARSER / if attribute is not an array we should not match equal to set', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -285,7 +285,7 @@ test('PARSER / if attribute is not an array we should not match equal to set', a test('PARSER / if attribute is an EMPTY array we should not match equal to set', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -318,7 +318,7 @@ test('PARSER / if attribute is an EMPTY array we should not match equal to set', test('PARSER / NEGATED if user.permissions ["read", "write"] equal to set ["read", "write"] then split 100:on should not match', async function () { const label = 'not permissions = ["read", "write"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -351,7 +351,7 @@ test('PARSER / NEGATED if user.permissions ["read", "write"] equal to set ["read test('PARSER / NEGATED if user.permissions ["read"] equal to set ["read", "write"] false, then match', async function () { const label = 'not permissions = ["read", "write"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -385,7 +385,7 @@ test('PARSER / NEGATED if user.permissions ["read"] equal to set ["read", "write test('PARSER / NEGATED if attribute is not an array we should not match equal to set, so match', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -422,7 +422,7 @@ test('PARSER / NEGATED if attribute is not an array we should not match equal to test('PARSER / NEGATED if attribute is an EMPTY array we should not match equal to set, so match', async function () { const label = 'countries = ["usa","argentina"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -459,7 +459,7 @@ test('PARSER / NEGATED if attribute is an EMPTY array we should not match equal // test('PARSER / if user.permissions ["read", "edit", "delete"] contains all of set ["read", "edit"] then split 100:on', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -494,7 +494,7 @@ test('PARSER / if user.permissions ["read", "edit", "delete"] contains all of se test('PARSER / if user.permissions ["edit", "read", "delete"] contains all of set ["read", "edit"] then split 100:on', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -529,7 +529,7 @@ test('PARSER / if user.permissions ["edit", "read", "delete"] contains all of se test('PARSER / if user.permissions [1, "edit", "delete"] contains all of set ["1", "edit"] then split 100:on', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -564,7 +564,7 @@ test('PARSER / if user.permissions [1, "edit", "delete"] contains all of set ["1 test('PARSER / if user.permissions ["read"] contains all of set ["read", "edit"] then not match', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -598,7 +598,7 @@ test('PARSER / if user.permissions ["read"] contains all of set ["read", "edit"] test('PARSER / if user.permissions ["read", "delete", "manage"] contains all of set ["read", "edit"] then not match', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -632,7 +632,7 @@ test('PARSER / if user.permissions ["read", "delete", "manage"] contains all of test('PARSER / if attribute is not an array we should not match contains all', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -667,7 +667,7 @@ test('PARSER / if attribute is not an array we should not match contains all', a test('PARSER / if attribute is an EMPTY array we should not match contains all', async function () { const label = 'permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -700,7 +700,7 @@ test('PARSER / if attribute is an EMPTY array we should not match contains all', test('PARSER / NEGATED if user.permissions ["read", "edit", "delete"] contains all of set ["read", "edit"] then split 100:on should not match', async function () { const label = 'not permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -733,7 +733,7 @@ test('PARSER / NEGATED if user.permissions ["read", "edit", "delete"] contains a test('PARSER / NEGATED if user.permissions ["read"] contains all of set ["read", "edit"] false, so match', async function () { const label = 'not permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -767,7 +767,7 @@ test('PARSER / NEGATED if user.permissions ["read"] contains all of set ["read", test('PARSER / NEGATED if attribute is not an array we should not match contains all, so match', async function () { const label = 'not permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -804,7 +804,7 @@ test('PARSER / NEGATED if attribute is not an array we should not match contains test('PARSER / NEGATED if attribute is an EMPTY array we should not match contains all, so match', async function () { const label = 'not permissions contains ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -841,7 +841,7 @@ test('PARSER / NEGATED if attribute is an EMPTY array we should not match contai // test('PARSER / if user.permissions ["read", "edit"] is part of set ["read", "edit", "delete"] then split 100:on', async function () { const label = 'permissions part of ["read", "edit", "delete"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -876,7 +876,7 @@ test('PARSER / if user.permissions ["read", "edit"] is part of set ["read", "edi test('PARSER / if user.permissions ["edit", "read"] is part of set ["read", "edit", "delete"] then split 100:on', async function () { const label = 'permissions part of ["read", "edit", "delete"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -911,7 +911,7 @@ test('PARSER / if user.permissions ["edit", "read"] is part of set ["read", "edi test('PARSER / if user.permissions [1, "edit"] is part of set ["1", "edit", "delete"] then split 100:on', async function () { const label = 'permissions part of ["1", "edit", "delete"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -946,7 +946,7 @@ test('PARSER / if user.permissions [1, "edit"] is part of set ["1", "edit", "del test('PARSER / if user.permissions ["admin", "magic"] is part of set ["read", "edit"] then not match', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -980,7 +980,7 @@ test('PARSER / if user.permissions ["admin", "magic"] is part of set ["read", "e test('PARSER / if attribute is not an array we should not match part of', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1015,7 +1015,7 @@ test('PARSER / if attribute is not an array we should not match part of', async test('PARSER / if attribute is an EMPTY array we should not match part of', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1048,7 +1048,7 @@ test('PARSER / if attribute is an EMPTY array we should not match part of', asyn test('PARSER / NEGATED if user.permissions ["read", "edit"] is part of set ["read", "edit", "delete"] then split 100:on should not match', async function () { const label = 'not permissions part of ["read", "edit", "delete"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1081,7 +1081,7 @@ test('PARSER / NEGATED if user.permissions ["read", "edit"] is part of set ["rea test('PARSER / NEGATED if user.permissions ["admin", "magic"] is part of set ["read", "edit"] false, then match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1115,7 +1115,7 @@ test('PARSER / NEGATED if user.permissions ["admin", "magic"] is part of set ["r test('PARSER / NEGATED if attribute is not an array we should not match part of, so match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1152,7 +1152,7 @@ test('PARSER / NEGATED if attribute is not an array we should not match part of, test('PARSER / NEGATED if attribute is an EMPTY array we should not match part of, so match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1189,7 +1189,7 @@ test('PARSER / NEGATED if attribute is an EMPTY array we should not match part o // test('PARSER / if user.permissions ["admin", "edit"] contains any of set ["read", "edit", "delete"] then split 100:on', async function () { const label = 'permissions part of ["read", "edit", "delete"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1224,7 +1224,7 @@ test('PARSER / if user.permissions ["admin", "edit"] contains any of set ["read" test('PARSER / if user.permissions ["admin", 1] contains any of set ["read", "1", "delete"] then split 100:on', async function () { const label = 'permissions part of ["read", "1", "delete"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1259,7 +1259,7 @@ test('PARSER / if user.permissions ["admin", 1] contains any of set ["read", "1" test('PARSER / if user.permissions ["admin", "magic"] contains any of set ["read", "edit"] then not match', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1293,7 +1293,7 @@ test('PARSER / if user.permissions ["admin", "magic"] contains any of set ["read test('PARSER / if attribute is not an array we should not match contains any', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1328,7 +1328,7 @@ test('PARSER / if attribute is not an array we should not match contains any', a test('PARSER / if attribute is an EMPTY array we should not match contains any', async function () { const label = 'permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1361,7 +1361,7 @@ test('PARSER / if attribute is an EMPTY array we should not match contains any', test('PARSER / NEGATED if user.permissions ["admin", "edit"] contains any of set ["read", "edit", "delete"] then split 100:on should not match', async function () { const label = 'not permissions part of ["read", "edit", "delete"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1394,7 +1394,7 @@ test('PARSER / NEGATED if user.permissions ["admin", "edit"] contains any of set test('PARSER / NEGATED if user.permissions ["admin", "magic"] contains any of set ["read", "edit"] false, then should match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1428,7 +1428,7 @@ test('PARSER / NEGATED if user.permissions ["admin", "magic"] contains any of se test('PARSER / NEGATED if attribute is not an array we should not match contains any, then should match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1460,7 +1460,7 @@ test('PARSER / NEGATED if attribute is not an array we should not match contains test('PARSER / NEGATED if attribute is an EMPTY array we should not match contains any, then should match', async function () { const label = 'not permissions part of ["read", "edit"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/string.spec.ts b/src/evaluator/parser/__tests__/string.spec.ts index d40c7f7e..326ade21 100644 --- a/src/evaluator/parser/__tests__/string.spec.ts +++ b/src/evaluator/parser/__tests__/string.spec.ts @@ -2,14 +2,14 @@ import parser from '..'; import { ISplitCondition } from '../../../dtos/types'; import { keyParser } from '../../../utils/key'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; // // STARTS WITH // test('PARSER / if user.email starts with ["nico"] then split 100:on', async function () { const label = 'email starts with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -43,7 +43,7 @@ test('PARSER / if user.email starts with ["nico"] then split 100:on', async func test('PARSER / if user.email = 123, starts with ["1"] then split 100:on should match', async function () { const label = 'email starts with ["1"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -77,7 +77,7 @@ test('PARSER / if user.email = 123, starts with ["1"] then split 100:on should m test('PARSER / if user.email starts with ["nico", "marcio", "facu"] then split 100:on', async function () { const label = 'email starts with ["nico", "marcio", "facu"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -111,7 +111,7 @@ test('PARSER / if user.email starts with ["nico", "marcio", "facu"] then split 1 test('PARSER / if user.email starts with ["nico", "marcio", "facu"] then split 100:on', async function () { const label = 'email starts with ["nico", "marcio", "facu"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -145,7 +145,7 @@ test('PARSER / if user.email starts with ["nico", "marcio", "facu"] then split 1 test('PARSER / if user.email does not start with ["nico"] then not match', async function () { // const label = 'email starts with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -177,7 +177,7 @@ test('PARSER / if user.email does not start with ["nico"] then not match', async test('PARSER / if user.email is an EMPTY string, start with ["nico"] should not match', async function () { // const label = 'email starts with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -207,7 +207,7 @@ test('PARSER / if user.email is an EMPTY string, start with ["nico"] should not test('PARSER / if user.email is not a string, start with ["nico"] should not match', async function () { // const label = 'email starts with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -240,7 +240,7 @@ test('PARSER / if user.email is not a string, start with ["nico"] should not mat test('PARSER / NEGATED if user.email starts with ["nico"] then split 100:on, so not match', async function () { const label = 'not email starts with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -273,7 +273,7 @@ test('PARSER / NEGATED if user.email starts with ["nico"] then split 100:on, so test('PARSER / NEGATED if user.email does not start with ["nico"] should not match, then match', async function () { const label = 'not email starts with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -307,7 +307,7 @@ test('PARSER / NEGATED if user.email does not start with ["nico"] should not mat test('PARSER / NEGATED if user.email is an EMPTY string, start with ["nico"] should not match, so negation should', async function () { const label = 'not email starts with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -339,7 +339,7 @@ test('PARSER / NEGATED if user.email is an EMPTY string, start with ["nico"] sho test('PARSER / NEGATED if user.email is not a string, start with ["nico"] should not match, so negation should', async function () { const label = 'not email starts with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -378,7 +378,7 @@ test('PARSER / NEGATED if user.email is not a string, start with ["nico"] should // test('PARSER / if user.email ends with ["split.io"] then split 100:on', async function () { const label = 'email ends with ["split.io"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -412,7 +412,7 @@ test('PARSER / if user.email ends with ["split.io"] then split 100:on', async fu test('PARSER / if user.email = 123, ends with ["3"] then split 100:on should match', async function () { const label = 'email starts with ["3"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -445,7 +445,7 @@ test('PARSER / if user.email = 123, ends with ["3"] then split 100:on should mat test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] then split 100:on', async function () { const label = 'email ends with ["gmail.com", "split.io", "hotmail.com"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -479,7 +479,7 @@ test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] then split 100:on', async function () { const label = 'email ends with ["gmail.com", "split.io", "hotmail.com"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -513,7 +513,7 @@ test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] but attribute is "" then split 100:on', async function () { const label = 'email ends with ["gmail.com", "split.io", "hotmail.com"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -546,7 +546,7 @@ test('PARSER / if user.email ends with ["gmail.com", "split.io", "hotmail.com"] test('PARSER / if user.email does not end with ["split.io"] then not match', async function () { const label = 'email ends with ["split.io"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -579,7 +579,7 @@ test('PARSER / if user.email does not end with ["split.io"] then not match', asy test('PARSER / if user.email is an EMPTY string, end with ["nico"] should not match', async function () { // const label = 'email ends with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -609,7 +609,7 @@ test('PARSER / if user.email is an EMPTY string, end with ["nico"] should not ma test('PARSER / if user.email is not a string, end with ["nico"] should not match', async function () { // const label = 'email ends with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -644,7 +644,7 @@ test('PARSER / if user.email is not a string, end with ["nico"] should not match test('PARSER / NEGATED if user.email ends with ["split.io"] then split 100:on, so not match', async function () { const label = 'not email ends with ["split.io"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -676,7 +676,7 @@ test('PARSER / NEGATED if user.email ends with ["split.io"] then split 100:on, s test('PARSER / NEGATED if user.email does not end with ["split.io"] then no match, so match', async function () { const label = 'not email ends with ["split.io"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -709,7 +709,7 @@ test('PARSER / NEGATED if user.email does not end with ["split.io"] then no matc test('PARSER / NEGATED if user.email is an EMPTY string, end with ["nico"] should not match, so negation should', async function () { const label = 'not email ends with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -741,7 +741,7 @@ test('PARSER / NEGATED if user.email is an EMPTY string, end with ["nico"] shoul test('PARSER / NEGATED if user.email is not a string, end with ["nico"] should not match, so negation should', async function () { const label = 'not email ends with ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -780,7 +780,7 @@ test('PARSER / NEGATED if user.email is not a string, end with ["nico"] should n // test('PARSER / if user.email contains ["@split"] then split 100:on', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -814,7 +814,7 @@ test('PARSER / if user.email contains ["@split"] then split 100:on', async funct test('PARSER / if user.email = 123, contains ["2"] then split 100:on should match', async function () { const label = 'email contains ["2"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -848,7 +848,7 @@ test('PARSER / if user.email = 123, contains ["2"] then split 100:on should matc test('PARSER / if user.email contains ["@split"] (beginning) then split 100:on', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -882,7 +882,7 @@ test('PARSER / if user.email contains ["@split"] (beginning) then split 100:on', test('PARSER / if user.email contains ["@split"] (end) then split 100:on', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -916,7 +916,7 @@ test('PARSER / if user.email contains ["@split"] (end) then split 100:on', async test('PARSER / if user.email contains ["@split"] (whole string matches) then split 100:on', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -950,7 +950,7 @@ test('PARSER / if user.email contains ["@split"] (whole string matches) then spl test('PARSER / if user.email contains ["@split", "@gmail", "@hotmail"] then split 100:on', async function () { const label = 'email contains ["@split", "@gmail", "@hotmail"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -984,7 +984,7 @@ test('PARSER / if user.email contains ["@split", "@gmail", "@hotmail"] then spli test('PARSER / if user.email contains ["@split", "@gmail", "@hotmail"] then split 100:on', async function () { const label = 'email contains ["@split", "@gmail", "@hotmail"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1018,7 +1018,7 @@ test('PARSER / if user.email contains ["@split", "@gmail", "@hotmail"] then spli test('PARSER / if user.email does not contain ["@split"] then not match', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1051,7 +1051,7 @@ test('PARSER / if user.email does not contain ["@split"] then not match', async test('PARSER / if user.email is an EMPTY string, contains ["nico"] should not match', async function () { // const label = 'email contains ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1081,7 +1081,7 @@ test('PARSER / if user.email is an EMPTY string, contains ["nico"] should not ma test('PARSER / if user.email is not a string, contains ["nico"] should not match', async function () { // const label = 'email contains ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1116,7 +1116,7 @@ test('PARSER / if user.email is not a string, contains ["nico"] should not match test('PARSER / NEGATED if user.email contains ["@split"] then split 100:on, then no match', async function () { const label = 'not email contains ["@split"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1149,7 +1149,7 @@ test('PARSER / NEGATED if user.email contains ["@split"] then split 100:on, then test('PARSER / NEGATED if user.email does not contain ["@split"] then not match, so match', async function () { const label = 'email contains ["@split"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1182,7 +1182,7 @@ test('PARSER / NEGATED if user.email does not contain ["@split"] then not match, test('PARSER / NEGATED if user.email is an EMPTY string, contains ["nico"] should not match, so negation should', async function () { const label = 'not email contains ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ @@ -1214,7 +1214,7 @@ test('PARSER / NEGATED if user.email is an EMPTY string, contains ["nico"] shoul test('PARSER / NEGATED if user.email is not a string, contains ["nico"] should not match, so negation should', async function () { const label = 'not email contains ["nico"]'; - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ matcherGroup: { combiner: 'AND', matchers: [{ diff --git a/src/evaluator/parser/__tests__/trafficAllocation.spec.ts b/src/evaluator/parser/__tests__/trafficAllocation.spec.ts index fec085f3..ddf5afae 100644 --- a/src/evaluator/parser/__tests__/trafficAllocation.spec.ts +++ b/src/evaluator/parser/__tests__/trafficAllocation.spec.ts @@ -3,11 +3,11 @@ import parser from '..'; import { keyParser } from '../../../utils/key'; import { ISplitCondition } from '../../../dtos/types'; import { IEvaluation } from '../../types'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('PARSER / if user is in segment all 100%:on but trafficAllocation is 0%', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ conditionType: 'ROLLOUT', matcherGroup: { combiner: 'AND', @@ -34,7 +34,7 @@ test('PARSER / if user is in segment all 100%:on but trafficAllocation is 0%', a test('PARSER / if user is in segment all 100%:on but trafficAllocation is 99% with bucket below 99', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ conditionType: 'ROLLOUT', matcherGroup: { combiner: 'AND', @@ -61,7 +61,7 @@ test('PARSER / if user is in segment all 100%:on but trafficAllocation is 99% wi test('PARSER / if user is in segment all 100%:on but trafficAllocation is 99% and bucket returns 100', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ conditionType: 'ROLLOUT', matcherGroup: { combiner: 'AND', @@ -88,7 +88,7 @@ test('PARSER / if user is in segment all 100%:on but trafficAllocation is 99% an test('PARSER / if user is whitelisted and in segment all 100%:off with trafficAllocation as 0%', async function () { - const evaluator = parser(noopLogger, [{ + const evaluator = parser(loggerMock, [{ conditionType: 'WHITELIST', matcherGroup: { combiner: 'AND', diff --git a/src/logger/noopLogger.ts b/src/logger/noopLogger.ts deleted file mode 100644 index df89763d..00000000 --- a/src/logger/noopLogger.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ILogger } from './types'; - -export const noopLogger: ILogger = { - debug() {}, - info() {}, - warn() {}, - error() {}, -}; diff --git a/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts b/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts index b8105afd..65bc828b 100644 --- a/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts +++ b/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts @@ -1,9 +1,9 @@ import SplitsCacheInLocal from '../SplitsCacheInLocal'; import KeyBuilderCS from '../../KeyBuilderCS'; -import { noopLogger } from '../../../logger/noopLogger'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('SPLIT CACHE / LocalStorage', () => { - const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(loggerMock, new KeyBuilderCS('SPLITIO', 'user')); cache.clear(); @@ -44,7 +44,7 @@ test('SPLIT CACHE / LocalStorage', () => { }); test('SPLIT CACHE / LocalStorage / Get Keys', () => { - const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(loggerMock, new KeyBuilderCS('SPLITIO', 'user')); cache.addSplit('lol1', 'something'); cache.addSplit('lol2', 'something else'); @@ -56,7 +56,7 @@ test('SPLIT CACHE / LocalStorage / Get Keys', () => { }); test('SPLIT CACHE / LocalStorage / Add Splits', () => { - const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(loggerMock, new KeyBuilderCS('SPLITIO', 'user')); cache.addSplits([ ['lol1', 'something'], @@ -70,7 +70,7 @@ test('SPLIT CACHE / LocalStorage / Add Splits', () => { }); test('SPLIT CACHE / LocalStorage / trafficTypeExists and ttcache tests', () => { - const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(loggerMock, new KeyBuilderCS('SPLITIO', 'user')); cache.addSplits([ // loop of addSplit ['split1', '{ "trafficTypeName": "user_tt" }'], @@ -109,7 +109,7 @@ test('SPLIT CACHE / LocalStorage / trafficTypeExists and ttcache tests', () => { }); test('SPLIT CACHE / LocalStorage / killLocally', () => { - const cache = new SplitsCacheInLocal(noopLogger, new KeyBuilderCS('SPLITIO', 'user')); + const cache = new SplitsCacheInLocal(loggerMock, new KeyBuilderCS('SPLITIO', 'user')); cache.addSplit('lol1', '{ "name": "something"}'); cache.addSplit('lol2', '{ "name": "something else"}'); const initialChangeNumber = cache.getChangeNumber(); From a972551b7b7781ce09983c054a87a1928cf297d1 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 4 Mar 2021 12:25:24 -0300 Subject: [PATCH 10/58] validate logger at settings --- src/logger/__tests__/index.spec.ts | 16 +++++----- src/sdkFactory/index.ts | 2 +- src/sdkFactory/types.ts | 4 +-- .../__tests__/index.asyncCache.spec.ts | 2 +- .../__tests__/index.syncCache.spec.ts | 2 +- src/sdkManager/index.ts | 4 +-- src/storages/AbstractSplitsCacheSync.ts | 3 +- .../__tests__/index.spec.ts | 4 +-- src/utils/settingsValidation/index.ts | 19 +++++++----- src/utils/settingsValidation/logger.ts | 30 +++++++++++++++++++ src/utils/settingsValidation/types.ts | 7 +++-- 11 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 src/utils/settingsValidation/logger.ts diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index c993df23..4ab2d782 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -34,10 +34,10 @@ test('SPLIT LOGGER / Logger class shape', () => { const logger = new Logger('test-category', {}); - expect(typeof logger.debug).toBe('function'); // instance.d should be a method. - expect(typeof logger.info).toBe('function'); // instance.i should be a method. - expect(typeof logger.warn).toBe('function'); // instance.w should be a method. - expect(typeof logger.error).toBe('function'); // instance.e should be a method. + expect(typeof logger.debug).toBe('function'); // instance.debug should be a method. + expect(typeof logger.info).toBe('function'); // instance.info should be a method. + expect(typeof logger.warn).toBe('function'); // instance.warn should be a method. + expect(typeof logger.error).toBe('function'); // instance.error should be a method. }); @@ -105,22 +105,22 @@ function testLogLevels(levelToTest: string) { } -test('SPLIT LOGGER / Logger class public methods behaviour - instance.d', () => { +test('SPLIT LOGGER / Logger class public methods behaviour - instance.debug', () => { testLogLevels(LogLevels.DEBUG); }); -test('SPLIT LOGGER / Logger class public methods behaviour - instance.i', () => { +test('SPLIT LOGGER / Logger class public methods behaviour - instance.info', () => { testLogLevels(LogLevels.INFO); }); -test('SPLIT LOGGER / Logger class public methods behaviour - instance.w', () => { +test('SPLIT LOGGER / Logger class public methods behaviour - instance.warn', () => { testLogLevels(LogLevels.WARN); }); -test('SPLIT LOGGER / Logger class public methods behaviour - instance.e', () => { +test('SPLIT LOGGER / Logger class public methods behaviour - instance.error', () => { testLogLevels(LogLevels.ERROR); }); diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index ace32dc0..2288e95b 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -74,7 +74,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // Sdk client and manager const clientMethod = sdkClientMethodFactory({ eventTracker, impressionsTracker, sdkReadinessManager, settings, storage, syncManager, signalListener }); - const managerInstance = sdkManagerFactory && sdkManagerFactory(storage.splits, sdkReadinessManager, log); + const managerInstance = sdkManagerFactory && sdkManagerFactory(log, storage.splits, sdkReadinessManager); syncManager && syncManager.start(); signalListener && signalListener.start(); diff --git a/src/sdkFactory/types.ts b/src/sdkFactory/types.ts index 2799234b..95355d82 100644 --- a/src/sdkFactory/types.ts +++ b/src/sdkFactory/types.ts @@ -47,9 +47,9 @@ export interface ISdkFactoryParams { // Sdk manager factory sdkManagerFactory?: ( + log: ILogger, splits: ISplitsCacheSync | ISplitsCacheAsync, - sdkReadinessManager: ISdkReadinessManager, - log: ILogger + sdkReadinessManager: ISdkReadinessManager ) => SplitIO.IManager | SplitIO.IAsyncManager, // Sdk client method factory (ISDK::client method). diff --git a/src/sdkManager/__tests__/index.asyncCache.spec.ts b/src/sdkManager/__tests__/index.asyncCache.spec.ts index 0694f04f..46cffb11 100644 --- a/src/sdkManager/__tests__/index.asyncCache.spec.ts +++ b/src/sdkManager/__tests__/index.asyncCache.spec.ts @@ -22,7 +22,7 @@ test('MANAGER API / Async cache (In Redis)', async () => { const connection = new Redis({}); // @ts-expect-error const keys = new KeyBuilderSS(); const cache = new SplitsCacheInRedis(loggerMock, keys, connection); - const manager = sdkManagerFactory(cache, sdkReadinessManagerMock, loggerMock); + const manager = sdkManagerFactory(loggerMock, cache, sdkReadinessManagerMock); await cache.clear(); await cache.addSplit(splitObject.name, JSON.stringify(splitObject)); diff --git a/src/sdkManager/__tests__/index.syncCache.spec.ts b/src/sdkManager/__tests__/index.syncCache.spec.ts index 8880b90a..4da65cd4 100644 --- a/src/sdkManager/__tests__/index.syncCache.spec.ts +++ b/src/sdkManager/__tests__/index.syncCache.spec.ts @@ -18,7 +18,7 @@ describe('MANAGER API / Sync cache (In Memory)', () => { /** Setup: create manager */ const cache = new SplitsCacheInMemory(); - const manager = sdkManagerFactory(cache, sdkReadinessManagerMock, loggerMock); + const manager = sdkManagerFactory(loggerMock, cache, sdkReadinessManagerMock); cache.addSplit(splitObject.name, JSON.stringify(splitObject)); test('List all splits', () => { diff --git a/src/sdkManager/index.ts b/src/sdkManager/index.ts index 779479c8..631d1c0c 100644 --- a/src/sdkManager/index.ts +++ b/src/sdkManager/index.ts @@ -52,9 +52,9 @@ function objectsToViews(jsons: string[]) { } export function sdkManagerFactory( + log: ILogger, splits: TSplitCache, - { readinessManager, sdkStatus }: ISdkReadinessManager, - log: ILogger + { readinessManager, sdkStatus }: ISdkReadinessManager ): TSplitCache extends ISplitsCacheAsync ? SplitIO.IAsyncManager : SplitIO.IManager { const SPLIT_FN_LABEL = 'split'; diff --git a/src/storages/AbstractSplitsCacheSync.ts b/src/storages/AbstractSplitsCacheSync.ts index 39eeebeb..46397fc3 100644 --- a/src/storages/AbstractSplitsCacheSync.ts +++ b/src/storages/AbstractSplitsCacheSync.ts @@ -89,7 +89,8 @@ export default abstract class AbstractSplitsCacheSync implements ISplitsCacheSyn * Given a parsed split, it returns a boolean flagging if its conditions use segments matchers (rules & whitelists). * This util is intended to simplify the implementation of `splitsCache::usesSegments` method */ -export function usesSegments({ conditions = [] }: ISplit) { +export function usesSegments(split: ISplit) { + const conditions = split.conditions || []; for (let i = 0; i < conditions.length; i++) { const matchers = conditions[i].matcherGroup.matchers; diff --git a/src/utils/settingsValidation/__tests__/index.spec.ts b/src/utils/settingsValidation/__tests__/index.spec.ts index 8399060b..df4a9fa6 100644 --- a/src/utils/settingsValidation/__tests__/index.spec.ts +++ b/src/utils/settingsValidation/__tests__/index.spec.ts @@ -167,7 +167,7 @@ describe('settingsValidation', () => { expect(settings.integrations).toBe(integrationsMock); expect(settings.storage).toBe(storageValidatorResult); - expect(storageValidatorMock).toBeCalledWith(settings); + expect(storageValidatorMock).toBeCalledWith(settings.log, settings); }); test('overwrites integrations with the result of the given integrations validator', () => { @@ -184,7 +184,7 @@ describe('settingsValidation', () => { expect(settings.storage).toBe(storageMock); expect(settings.integrations).toBe(integrationsValidatorResult); - expect(integrationsValidatorMock).toBeCalledWith(settings); + expect(integrationsValidatorMock).toBeCalledWith(settings.log, settings); }); }); diff --git a/src/utils/settingsValidation/index.ts b/src/utils/settingsValidation/index.ts index 655787b9..d5f037ba 100644 --- a/src/utils/settingsValidation/index.ts +++ b/src/utils/settingsValidation/index.ts @@ -1,4 +1,5 @@ import { merge } from '../lang'; +import logger from './logger'; import mode from './mode'; import { validateSplitFilters } from './splitFilters'; import { API } from '../../logger/sdkLogger'; @@ -6,8 +7,6 @@ import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE } from '../constants'; import validImpressionsMode from './impressionsMode'; import { LogLevel } from '../../types'; import { ISettingsInternal, ISettingsValidationParams } from './types'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio'); const base = { // Define which kind of object you want to retrieve from SplitFactory @@ -82,8 +81,8 @@ const base = { impressionsMode: OPTIMIZED }, - // base logger - log + // Logger + log: undefined }; function fromSecondsToMillis(n: number) { @@ -128,13 +127,17 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV withDefaults.startup.readyTimeout = fromSecondsToMillis(withDefaults.startup.readyTimeout); withDefaults.startup.eventsFirstPushWindow = fromSecondsToMillis(withDefaults.startup.eventsFirstPushWindow); + // ensure a valid logger + const log = logger(withDefaults); // @ts-ignore + withDefaults.log = log; + // ensure a valid SDK mode // @ts-ignore withDefaults.mode = mode(withDefaults.core.authorizationKey, withDefaults.mode); // ensure a valid Storage based on mode defined. // @ts-ignore - if (storage) withDefaults.storage = storage(withDefaults); + if (storage) withDefaults.storage = storage(log, withDefaults); setupLogger(withDefaults.debug); @@ -150,7 +153,7 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV // ensure a valid list of integrations. // `integrations` returns an array of valid integration items. // @ts-ignore - if (integrations) withDefaults.integrations = integrations(withDefaults); + if (integrations) withDefaults.integrations = integrations(log, withDefaults); // validate push options if (withDefaults.streamingEnabled !== false) { // @ts-ignore @@ -162,12 +165,12 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV } // validate the `splitFilters` settings and parse splits query - const splitFiltersValidation = validateSplitFilters(withDefaults.log, withDefaults.sync.splitFilters, withDefaults.mode); + const splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters, withDefaults.mode); withDefaults.sync.splitFilters = splitFiltersValidation.validFilters; // @ts-ignore withDefaults.sync.__splitFiltersValidation = splitFiltersValidation; // ensure a valid impressionsMode - withDefaults.sync.impressionsMode = validImpressionsMode(withDefaults.log, withDefaults.sync.impressionsMode); + withDefaults.sync.impressionsMode = validImpressionsMode(log, withDefaults.sync.impressionsMode); return withDefaults; } diff --git a/src/utils/settingsValidation/logger.ts b/src/utils/settingsValidation/logger.ts new file mode 100644 index 00000000..cfd39fbf --- /dev/null +++ b/src/utils/settingsValidation/logger.ts @@ -0,0 +1,30 @@ +import { ILogger } from '../../logger/types'; + +const noopLogger = { + debug() { }, + info() { }, + warn() { }, + error() { } +}; + +function isLogger(log: unknown): log is ILogger { + // @ts-ignore + return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function'; +} + +/** + * Validates the `log` (logger) property at config. + * + * @param settings user config object + * @returns the provided logger or a no-op logger if no one is provided + * @throws throws an error if a logger was provided but is invalid + */ +export default function logger(settings: { log: unknown }): ILogger { + const { log } = settings; + + if (!log) return noopLogger; + + if (isLogger(log)) return log; + + throw new Error('The provided `log` value at config is not valid'); +} diff --git a/src/utils/settingsValidation/types.ts b/src/utils/settingsValidation/types.ts index d2845582..798b706f 100644 --- a/src/utils/settingsValidation/types.ts +++ b/src/utils/settingsValidation/types.ts @@ -1,4 +1,5 @@ import { ISplitFiltersValidation } from '../../dtos/types'; +import { ILogger } from '../../logger/types'; import { ISettings } from '../../types'; /** @@ -10,11 +11,11 @@ export interface ISettingsValidationParams { * Version and startup properties are mandatory, because these values are not part of the base setting. */ defaults: Partial & { version: string } & { startup: ISettings['startup'] }, - runtime: (settings: ISettings) => ISettings['runtime'], + runtime: (log: ILogger, settings: ISettings) => ISettings['runtime'], /** Storage validator */ - storage?: (settings: ISettings) => ISettings['storage'], + storage?: (log: ILogger, settings: ISettings) => ISettings['storage'], /** Integrations validator */ - integrations?: (settings: ISettings) => ISettings['integrations'], + integrations?: (log: ILogger, settings: ISettings) => ISettings['integrations'], } /** From 79534e1f1b78de0aaff27dcf3bef0c4d8859a8a4 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 4 Mar 2021 20:40:11 -0300 Subject: [PATCH 11/58] replaced ICodes by a single Map --- src/logger/__tests__/index.spec.ts | 5 ++--- src/logger/codes.ts | 9 --------- src/logger/index.ts | 11 ++++++----- src/logger/sdkLogger.ts | 5 +++-- src/logger/types.ts | 4 ---- src/utils/timeTracker/index.ts | 3 +-- 6 files changed, 12 insertions(+), 25 deletions(-) delete mode 100644 src/logger/codes.ts diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index 43f99bd5..47840542 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -1,5 +1,4 @@ import { Logger, LogLevels, setLogLevel, isLogLevelString } from '../index'; -import { codes } from '../codes'; import { LogLevel } from '../../types'; // We'll set this only once. These are the constants we will use for @@ -34,7 +33,7 @@ test('SPLIT LOGGER / LogLevels exposed mappings', () => { test('SPLIT LOGGER / Logger class shape', () => { expect(typeof Logger).toBe('function'); // Logger should be a class we can instantiate. - const logger = new Logger('test-category', {}, codes); + const logger = new Logger('test-category', {}); expect(typeof logger.debug).toBe('function'); // instance.debug should be a method. expect(typeof logger.info).toBe('function'); // instance.info should be a method. @@ -66,7 +65,7 @@ function testLogLevels(levelToTest: LogLevel) { const logCategory = `test-category-${logMethod}${displayAllErrors ? 'displayAllErrors' : ''}`; const instance = new Logger(logCategory, { showLevel, displayAllErrors - }, codes); + }); LOG_LEVELS_IN_ORDER.forEach((logLevel: LogLevel, i) => { const logMsg = `Test log for level ${levelToTest} (${displayAllErrors ? 'But all errors are configured to display' : 'Errors not forced to display'}) with showLevel: ${showLevel} ${logLevelLogsCounter}`; diff --git a/src/logger/codes.ts b/src/logger/codes.ts deleted file mode 100644 index bba7665d..00000000 --- a/src/logger/codes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ICodes } from './types'; - -export const codes: ICodes = { - DEBUG: [], - ERROR: [], - INFO: [], - WARN: [], - NONE: [], -}; diff --git a/src/logger/index.ts b/src/logger/index.ts index 14a3afcf..af2d75ca 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -1,7 +1,8 @@ import objectAssign from 'object-assign'; -import { ILoggerOptions, ILogger, ICodes } from './types'; +import { ILoggerOptions, ILogger } from './types'; import { find } from '../utils/lang'; import { LogLevel } from '../types'; +import { IMap, _Map } from '../utils/lang/maps'; export const LogLevels: { [level in LogLevel]: LogLevel } = { DEBUG: 'DEBUG', @@ -38,12 +39,12 @@ export class Logger implements ILogger { private category?: string; private options: ILoggerOptions; - private codes: ICodes; + private codes: IMap; - constructor(category: string | undefined, options: ILoggerOptions | undefined, codes: ICodes) { + constructor(category: string | undefined, options: ILoggerOptions | undefined, codes?: IMap) { this.category = category; this.options = objectAssign({}, defaultOptions, options); - this.codes = codes; + this.codes = codes || new _Map(); } debug(msg: string | number, args?: any[]) { @@ -67,7 +68,7 @@ export class Logger implements ILogger { } private _log(level: LogLevel, text: string | number, args?: any[]) { - if (typeof text === 'number') text = sprintf(this.codes[level][text], args); + if (typeof text === 'number') text = sprintf(this.codes.get(text), args); const formattedText = this._generateLogMessage(level, text); console.log(formattedText); diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 8c880c9e..120c9288 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -1,12 +1,13 @@ /** * This file defines the logger interface and default options for the SDKs, not necessarily for the Logger as it's own. */ -import { ICodes, ILoggerOptions } from './types'; +import { ILoggerOptions } from './types'; import { Logger, LogLevels, setLogLevel, isLogLevelString } from '.'; import { isLocalStorageAvailable } from '../utils/env/isLocalStorageAvailable'; import { isNode } from '../utils/env/isNode'; import { merge } from '../utils/lang'; import { ILoggerAPI } from '../types'; +import { IMap } from '../utils/lang/maps'; // @TODO when integrating with other packages, find the best way to update LoggerOption defaults per package (node, evaluator, etc.) const defaultOptions: ILoggerOptions = { @@ -30,7 +31,7 @@ const initialState = String( ); // we expose the logger instance creator -export const logFactory = (namespace: string, options = {}, codes: ICodes) => new Logger(namespace, merge(options, defaultOptions), codes); +export const logFactory = (namespace: string, options = {}, codes: IMap) => new Logger(namespace, merge(options, defaultOptions), codes); // const log = logFactory('splitio-utils:logger'); diff --git a/src/logger/types.ts b/src/logger/types.ts index 9ca8a08a..16d84e92 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -1,5 +1,3 @@ -import { LogLevel } from '../types'; - export interface ILoggerOptions { showLevel?: boolean, displayAllErrors?: boolean @@ -14,5 +12,3 @@ export interface ILogger { error(msg: string | number, args?: any[]): void } - -export type ICodes = { [level in LogLevel]: string[] } diff --git a/src/utils/timeTracker/index.ts b/src/utils/timeTracker/index.ts index 4d988233..fa2dccb3 100644 --- a/src/utils/timeTracker/index.ts +++ b/src/utils/timeTracker/index.ts @@ -2,7 +2,6 @@ import { uniqueId } from '../lang'; import { Logger } from '../../logger/index'; import timer from './timer'; import thenable from '../promise/thenable'; -import { codes } from '../../logger/codes'; // Based on ProducerMetricsCollector and ClientCollector classes interface MetricsCollector { @@ -24,7 +23,7 @@ interface MetricsCollector { // logger to be used on this module const logger = new Logger('[TIME TRACKER]', { showLevel: false -}, codes); +}); // Map we will use for storing timers data const timers: Record Date: Thu, 4 Mar 2021 20:48:21 -0300 Subject: [PATCH 12/58] rollback logErrorsAsInfo --- src/services/splitApi.ts | 6 +++--- src/services/splitHttpClient.ts | 4 ++-- src/services/types.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/services/splitApi.ts b/src/services/splitApi.ts index 76568e86..6e77854c 100644 --- a/src/services/splitApi.ts +++ b/src/services/splitApi.ts @@ -62,7 +62,7 @@ export function splitApiFactory(settings: ISettings, platform: IPlatform): ISpli postTestImpressionsBulk(body: string) { const url = `${urls.events}/testImpressions/bulk`; - return splitHttpClient(url, 'POST', body, { + return splitHttpClient(url, 'POST', body, false, { // Adding extra headers to send impressions in OPTIMIZED or DEBUG modes. SplitSDKImpressionsMode }); @@ -70,12 +70,12 @@ export function splitApiFactory(settings: ISettings, platform: IPlatform): ISpli postTestImpressionsCount(body: string) { const url = `${urls.events}/testImpressions/count`; - return splitHttpClient(url, 'POST', body); + return splitHttpClient(url, 'POST', body, true); }, postMetricsCounters(body: string) { const url = `${urls.events}/metrics/counters`; - return splitHttpClient(url, 'POST', body); + return splitHttpClient(url, 'POST', body, true); }, postMetricsTimes(body: string) { diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index a44055a6..f2fe6016 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -34,7 +34,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I if (metadata.ip) headers['SplitSDKMachineIP'] = metadata.ip; if (metadata.hostname) headers['SplitSDKMachineName'] = metadata.hostname; - return function httpClient(url: string, method: string = 'GET', body?: string, extraHeaders?: Record): Promise { + return function httpClient(url: string, method: string = 'GET', body?: string, logErrorsAsInfo: boolean = false, extraHeaders?: Record): Promise { const rHeaders = extraHeaders ? objectAssign({}, headers, extraHeaders) : headers; const request = objectAssign({ headers: rHeaders, method, body }, options); @@ -63,7 +63,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I } if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else. - log.error(`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); + log[logErrorsAsInfo ? 'info' : 'error'](`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); } // passes `undefined` as statusCode if not an HTTP error (resp === undefined) diff --git a/src/services/types.ts b/src/services/types.ts index f2603513..ba134f5d 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -8,7 +8,7 @@ export type IFetch = ( } ) => Promise -export type ISplitHttpClient = (url: string, method?: string, body?: string, extraHeaders?: Record) => Promise +export type ISplitHttpClient = (url: string, method?: string, body?: string, logErrorsAsInfo?: boolean, extraHeaders?: Record) => Promise export type IFetchAuth = (userKeys?: string[]) => Promise From d3f7282b6a1d137c8f5352430e9407e7362a8297 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 4 Mar 2021 21:24:11 -0300 Subject: [PATCH 13/58] polishing --- src/types.ts | 2 +- .../__tests__/index.spec.ts | 2 +- src/utils/settingsValidation/index.ts | 6 ++--- .../__tests__/configurable.spec.ts | 24 +++++++++---------- .../integrations/__tests__/plugable.spec.ts | 20 ++++++++-------- .../settingsValidation/integrations/common.ts | 4 ++-- .../integrations/configurable.ts | 3 +-- .../integrations/pluggable.ts | 3 +-- src/utils/settingsValidation/splitFilters.ts | 1 + .../storage/__tests__/storageCS.spec.ts | 14 +++++------ .../settingsValidation/storage/storageCS.ts | 4 ++-- src/utils/settingsValidation/types.ts | 7 +++--- 12 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/types.ts b/src/types.ts index c2093371..cbec6880 100644 --- a/src/types.ts +++ b/src/types.ts @@ -102,7 +102,7 @@ export interface ISettings { ip: string | false hostname: string | false }, - readonly log: ILogger + log: ILogger } /** * Log levels. diff --git a/src/utils/settingsValidation/__tests__/index.spec.ts b/src/utils/settingsValidation/__tests__/index.spec.ts index df4a9fa6..cf847414 100644 --- a/src/utils/settingsValidation/__tests__/index.spec.ts +++ b/src/utils/settingsValidation/__tests__/index.spec.ts @@ -184,7 +184,7 @@ describe('settingsValidation', () => { expect(settings.storage).toBe(storageMock); expect(settings.integrations).toBe(integrationsValidatorResult); - expect(integrationsValidatorMock).toBeCalledWith(settings.log, settings); + expect(integrationsValidatorMock).toBeCalledWith(settings); }); }); diff --git a/src/utils/settingsValidation/index.ts b/src/utils/settingsValidation/index.ts index d5f037ba..18fac9ed 100644 --- a/src/utils/settingsValidation/index.ts +++ b/src/utils/settingsValidation/index.ts @@ -128,7 +128,7 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV withDefaults.startup.eventsFirstPushWindow = fromSecondsToMillis(withDefaults.startup.eventsFirstPushWindow); // ensure a valid logger - const log = logger(withDefaults); // @ts-ignore + const log = logger(withDefaults); withDefaults.log = log; // ensure a valid SDK mode @@ -137,7 +137,7 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV // ensure a valid Storage based on mode defined. // @ts-ignore - if (storage) withDefaults.storage = storage(log, withDefaults); + if (storage) withDefaults.storage = storage(withDefaults); setupLogger(withDefaults.debug); @@ -153,7 +153,7 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV // ensure a valid list of integrations. // `integrations` returns an array of valid integration items. // @ts-ignore - if (integrations) withDefaults.integrations = integrations(log, withDefaults); + if (integrations) withDefaults.integrations = integrations(withDefaults); // validate push options if (withDefaults.streamingEnabled !== false) { // @ts-ignore diff --git a/src/utils/settingsValidation/integrations/__tests__/configurable.spec.ts b/src/utils/settingsValidation/integrations/__tests__/configurable.spec.ts index a6eaa23c..5c6989bb 100644 --- a/src/utils/settingsValidation/integrations/__tests__/configurable.spec.ts +++ b/src/utils/settingsValidation/integrations/__tests__/configurable.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock as log } from '../../../../logger/__tests__/sdkLogger.mock'; import { validateConfigurableIntegrations } from '../configurable'; @@ -6,14 +6,14 @@ describe('integration validator for the configurable integrations', () => { // Check different types, since `integrations` param is defined by the user test('Returns an empty array if `integrations` is an invalid object', () => { - expect(validateConfigurableIntegrations(loggerMock, {}, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations(loggerMock, { integrations: undefined }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations(loggerMock, { integrations: true }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations(loggerMock, { integrations: 123 }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations(loggerMock, { integrations: 'string' }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations(loggerMock, { integrations: {} }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations(loggerMock, { integrations: [] }, ['INT_TYPE'])).toEqual([]); - expect(validateConfigurableIntegrations(loggerMock, { integrations: [false, 0, Infinity, new Error(), () => { }, []] }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations({ log }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations({ log, integrations: undefined }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations({ log, integrations: true }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations({ log, integrations: 123 }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations({ log, integrations: 'string' }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations({ log, integrations: {} }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations({ log, integrations: [] }, ['INT_TYPE'])).toEqual([]); + expect(validateConfigurableIntegrations({ log, integrations: [false, 0, Infinity, new Error(), () => { }, []] }, ['INT_TYPE'])).toEqual([]); }); test('Filters invalid integrations from `integrations` array', () => { @@ -35,15 +35,15 @@ describe('integration validator for the configurable integrations', () => { }; // All integrations are removed if no `validIntegrationTypes` array is passed - expect(validateConfigurableIntegrations(loggerMock, { integrations: [valid, validWithOptions, invalid] })) + expect(validateConfigurableIntegrations({ log, integrations: [valid, validWithOptions, invalid] })) .toEqual([]); // Integrations that do not have the passed types are removed - expect(validateConfigurableIntegrations(loggerMock, { integrations: [valid, validWithOptions, otherValidWithOptions, invalid] }, ['INT1'])) + expect(validateConfigurableIntegrations({ log, integrations: [valid, validWithOptions, otherValidWithOptions, invalid] }, ['INT1'])) .toEqual([valid, validWithOptions]); // Integrations that do not have the passed types or are invalid objects are removed - expect(validateConfigurableIntegrations(loggerMock, { integrations: [invalid, valid, false, 0, validWithOptions, Infinity, new Error(), otherValidWithOptions, () => { }, [], invalid] }, ['INT1', 'INT2'])) + expect(validateConfigurableIntegrations({ log, integrations: [invalid, valid, false, 0, validWithOptions, Infinity, new Error(), otherValidWithOptions, () => { }, [], invalid] }, ['INT1', 'INT2'])) .toEqual([valid, validWithOptions, otherValidWithOptions]); }); }); diff --git a/src/utils/settingsValidation/integrations/__tests__/plugable.spec.ts b/src/utils/settingsValidation/integrations/__tests__/plugable.spec.ts index 15b6b6d4..a9b76aa1 100644 --- a/src/utils/settingsValidation/integrations/__tests__/plugable.spec.ts +++ b/src/utils/settingsValidation/integrations/__tests__/plugable.spec.ts @@ -1,18 +1,18 @@ import { validatePluggableIntegrations } from '../pluggable'; -import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock as log } from '../../../../logger/__tests__/sdkLogger.mock'; describe('integrations validator for pluggable integrations', () => { // Check different types, since `integrations` param is defined by the user test('Returns an empty array if `integrations` is an invalid object', () => { - expect(validatePluggableIntegrations(loggerMock, {})).toEqual([]); - expect(validatePluggableIntegrations(loggerMock, { integrations: undefined })).toEqual([]); - expect(validatePluggableIntegrations(loggerMock, { integrations: true })).toEqual([]); - expect(validatePluggableIntegrations(loggerMock, { integrations: 123 })).toEqual([]); - expect(validatePluggableIntegrations(loggerMock, { integrations: 'string' })).toEqual([]); - expect(validatePluggableIntegrations(loggerMock, { integrations: {} })).toEqual([]); - expect(validatePluggableIntegrations(loggerMock, { integrations: [] })).toEqual([]); - expect(validatePluggableIntegrations(loggerMock, { integrations: [false, 0, Infinity, new Error(), []] })).toEqual([]); + expect(validatePluggableIntegrations({ log })).toEqual([]); + expect(validatePluggableIntegrations({ log, integrations: undefined })).toEqual([]); + expect(validatePluggableIntegrations({ log, integrations: true })).toEqual([]); + expect(validatePluggableIntegrations({ log, integrations: 123 })).toEqual([]); + expect(validatePluggableIntegrations({ log, integrations: 'string' })).toEqual([]); + expect(validatePluggableIntegrations({ log, integrations: {} })).toEqual([]); + expect(validatePluggableIntegrations({ log, integrations: [] })).toEqual([]); + expect(validatePluggableIntegrations({ log, integrations: [false, 0, Infinity, new Error(), []] })).toEqual([]); }); test('Filters invalid integration factories from `integrations` array', () => { @@ -21,7 +21,7 @@ describe('integrations validator for pluggable integrations', () => { const invalid = { queue() { } }; // Integration factories that are invalid objects are removed - expect(validatePluggableIntegrations(loggerMock, { integrations: [invalid, validNoopIntFactory, false, 0, validIntFactory, Infinity, new Error(), [], invalid] })) + expect(validatePluggableIntegrations({ log, integrations: [invalid, validNoopIntFactory, false, 0, validIntFactory, Infinity, new Error(), [], invalid] })) .toEqual([validNoopIntFactory, validIntFactory]); }); diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index df33ee90..23031832 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -11,8 +11,8 @@ import { ILogger } from '../../../logger/types'; * * @returns {Array} array of valid integration items. The array might be empty if `settings` object does not have valid integrations. */ -export function validateIntegrations(log: ILogger, settings: any, integrationValidator: (integrationItem: any) => boolean, extraWarning?: string) { - const { integrations } = settings; +export function validateIntegrations(settings: { log: ILogger, integrations?: any }, integrationValidator: (integrationItem: any) => boolean, extraWarning?: string) { + const { integrations, log } = settings; // If integrations is not an array or an empty array, we return an empty array (no integrations). if (!Array.isArray(integrations) || integrations.length === 0) return []; diff --git a/src/utils/settingsValidation/integrations/configurable.ts b/src/utils/settingsValidation/integrations/configurable.ts index 29b3cc11..dd6d1383 100644 --- a/src/utils/settingsValidation/integrations/configurable.ts +++ b/src/utils/settingsValidation/integrations/configurable.ts @@ -10,10 +10,9 @@ import { ILogger } from '../../../logger/types'; * * @returns {Array} array of valid integration items. The array might be empty if `settings` object does not have valid integrations. */ -export function validateConfigurableIntegrations(log: ILogger, settings: any, validIntegrationTypes: string[] = []) { +export function validateConfigurableIntegrations(settings: { log: ILogger, integrations?: any }, validIntegrationTypes: string[] = []) { return validateIntegrations( - log, settings, integration => integration && isString(integration.type) && validIntegrationTypes.indexOf(integration.type) > -1, 'Integration items must have a valid \'type\' value' diff --git a/src/utils/settingsValidation/integrations/pluggable.ts b/src/utils/settingsValidation/integrations/pluggable.ts index a3012181..b4a96ee9 100644 --- a/src/utils/settingsValidation/integrations/pluggable.ts +++ b/src/utils/settingsValidation/integrations/pluggable.ts @@ -9,10 +9,9 @@ import { ILogger } from '../../../logger/types'; * * @returns {Array} array of valid integration factories. The array might be empty if `settings` object does not have valid integrations. */ -export function validatePluggableIntegrations(log: ILogger, settings: any): ISettings['integrations'] { +export function validatePluggableIntegrations(settings: { log: ILogger, integrations?: any }): ISettings['integrations'] { return validateIntegrations( - log, settings, integration => typeof integration === 'function', 'Integration items must be functions that initialize the integrations' diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index 4d25db12..e950ba48 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -76,6 +76,7 @@ function queryStringBuilder(groupedFilters: Record { // Check different types, since `storage` param is defined by the user test('fallbacks to default InMemory storage if the storage is invalid or not provided', () => { - expect(validateStorageCS(loggerMock, {})).toBe(InMemoryStorageCSFactory); - expect(validateStorageCS(loggerMock, { storage: undefined })).toBe(InMemoryStorageCSFactory); - expect(validateStorageCS(loggerMock, { storage: {} })).toBe(InMemoryStorageCSFactory); - expect(validateStorageCS(loggerMock, { storage: 'invalid storage' })).toBe(InMemoryStorageCSFactory); + expect(validateStorageCS({ log })).toBe(InMemoryStorageCSFactory); + expect(validateStorageCS({ log, storage: undefined })).toBe(InMemoryStorageCSFactory); + expect(validateStorageCS({ log, storage: {} })).toBe(InMemoryStorageCSFactory); + expect(validateStorageCS({ log, storage: 'invalid storage' })).toBe(InMemoryStorageCSFactory); }); test('returns the provided storage factory if it is valid', () => { - const mockStorageFactory = () => {}; - expect(validateStorageCS(loggerMock, { storage: mockStorageFactory })).toBe(mockStorageFactory); + const mockStorageFactory = () => { }; + expect(validateStorageCS({ log, storage: mockStorageFactory })).toBe(mockStorageFactory); }); }); diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index 674a21f9..40bfd221 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -11,8 +11,8 @@ import { ILogger } from '../../../logger/types'; * * @returns {Object} valid storage factory. It might be the default `InMemoryStorageCSFactory` if the provided storage is invalid. */ -export function validateStorageCS(log: ILogger, settings: any): ISettings['storage'] { - const { storage } = settings; +export function validateStorageCS(settings: { log: ILogger, storage?: any }): ISettings['storage'] { + const { storage, log } = settings; // validate storage // @TODO validate its API (Splits cache, MySegments cache, etc) when supporting custom storages diff --git a/src/utils/settingsValidation/types.ts b/src/utils/settingsValidation/types.ts index 798b706f..d2845582 100644 --- a/src/utils/settingsValidation/types.ts +++ b/src/utils/settingsValidation/types.ts @@ -1,5 +1,4 @@ import { ISplitFiltersValidation } from '../../dtos/types'; -import { ILogger } from '../../logger/types'; import { ISettings } from '../../types'; /** @@ -11,11 +10,11 @@ export interface ISettingsValidationParams { * Version and startup properties are mandatory, because these values are not part of the base setting. */ defaults: Partial & { version: string } & { startup: ISettings['startup'] }, - runtime: (log: ILogger, settings: ISettings) => ISettings['runtime'], + runtime: (settings: ISettings) => ISettings['runtime'], /** Storage validator */ - storage?: (log: ILogger, settings: ISettings) => ISettings['storage'], + storage?: (settings: ISettings) => ISettings['storage'], /** Integrations validator */ - integrations?: (log: ILogger, settings: ISettings) => ISettings['integrations'], + integrations?: (settings: ISettings) => ISettings['integrations'], } /** From 1ced58e3e88678d9827176963665be20b90a6543 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 4 Mar 2021 21:28:00 -0300 Subject: [PATCH 14/58] polishing --- src/logger/__tests__/sdkLogger.mock.ts | 10 ---------- src/utils/settingsValidation/__tests__/index.spec.ts | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/logger/__tests__/sdkLogger.mock.ts b/src/logger/__tests__/sdkLogger.mock.ts index 0ba6aa71..542c6b35 100644 --- a/src/logger/__tests__/sdkLogger.mock.ts +++ b/src/logger/__tests__/sdkLogger.mock.ts @@ -1,11 +1,3 @@ -/** - * This util mocks the logFactory at sdkLogger module, to spy on it - */ - -jest.mock('../sdkLogger'); - -import { logFactory } from '../sdkLogger'; - export const loggerMock = { warn: jest.fn(), error: jest.fn(), @@ -13,8 +5,6 @@ export const loggerMock = { info: jest.fn(), }; -(logFactory as jest.Mock).mockReturnValue(loggerMock); - export function mockClear() { loggerMock.warn.mockClear(); loggerMock.error.mockClear(); diff --git a/src/utils/settingsValidation/__tests__/index.spec.ts b/src/utils/settingsValidation/__tests__/index.spec.ts index cf847414..8399060b 100644 --- a/src/utils/settingsValidation/__tests__/index.spec.ts +++ b/src/utils/settingsValidation/__tests__/index.spec.ts @@ -167,7 +167,7 @@ describe('settingsValidation', () => { expect(settings.integrations).toBe(integrationsMock); expect(settings.storage).toBe(storageValidatorResult); - expect(storageValidatorMock).toBeCalledWith(settings.log, settings); + expect(storageValidatorMock).toBeCalledWith(settings); }); test('overwrites integrations with the result of the given integrations validator', () => { From fddce07efd03849c5a30e51c3cb59132407507de Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 4 Mar 2021 21:28:00 -0300 Subject: [PATCH 15/58] removed displayAllErrors option --- src/logger/__tests__/sdkLogger.mock.ts | 10 ------- src/logger/index.ts | 7 +++-- src/logger/sdkLogger.ts | 1 - src/logger/types.ts | 1 - .../polling/syncTasks/segmentsSyncTask.ts | 1 - src/utils/inputValidation/apiKey.ts | 5 +--- src/utils/inputValidation/isOperational.ts | 2 +- .../__tests__/index.spec.ts | 2 +- src/utils/timeTracker/index.ts | 26 +++++++++---------- 9 files changed, 18 insertions(+), 37 deletions(-) diff --git a/src/logger/__tests__/sdkLogger.mock.ts b/src/logger/__tests__/sdkLogger.mock.ts index 0ba6aa71..542c6b35 100644 --- a/src/logger/__tests__/sdkLogger.mock.ts +++ b/src/logger/__tests__/sdkLogger.mock.ts @@ -1,11 +1,3 @@ -/** - * This util mocks the logFactory at sdkLogger module, to spy on it - */ - -jest.mock('../sdkLogger'); - -import { logFactory } from '../sdkLogger'; - export const loggerMock = { warn: jest.fn(), error: jest.fn(), @@ -13,8 +5,6 @@ export const loggerMock = { info: jest.fn(), }; -(logFactory as jest.Mock).mockReturnValue(loggerMock); - export function mockClear() { loggerMock.warn.mockClear(); loggerMock.error.mockClear(); diff --git a/src/logger/index.ts b/src/logger/index.ts index d8fe71fd..e7da05af 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -24,12 +24,11 @@ export function isLogLevelString(str: string): str is LogLevel { const defaultOptions = { showLevel: true, - displayAllErrors: false }; export class Logger implements ILogger { - private category: any; - private options: any; + private category: string; + private options: Required; constructor(category: string, options: ILoggerOptions) { this.category = category; @@ -52,7 +51,7 @@ export class Logger implements ILogger { } error(msg: string) { - if (this.options.displayAllErrors || this._shouldLog(LogLevels.ERROR)) + if (this._shouldLog(LogLevels.ERROR)) this._log(LogLevels.ERROR, msg); } diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index a7dbe9a8..af11fdda 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -11,7 +11,6 @@ import { ILoggerAPI } from '../types'; // @TODO when integrating with other packages, find the best way to update LoggerOption defaults per package (node, evaluator, etc.) const defaultOptions: ILoggerOptions = { showLevel: true, - displayAllErrors: false }; // @TODO when integrating with other packages, find the best way to handle initial state per package/environment diff --git a/src/logger/types.ts b/src/logger/types.ts index 62ac8628..46a59273 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -1,6 +1,5 @@ export interface ILoggerOptions { showLevel?: boolean, - displayAllErrors?: boolean } export interface ILogger { diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index 90cefe37..e8290b52 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -12,7 +12,6 @@ import { ISettings } from '../../../types'; import { ILogger } from '../../../logger/types'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:segment-changes'); -// const inputValidationLog = logFactory('', { displayAllErrors: true }); type ISegmentChangesUpdater = (segmentNames?: string[]) => Promise diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index 5af87568..ec179426 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -1,10 +1,7 @@ import { ILogger } from '../../logger/types'; import { isString } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('', { -// // Errors on API key validation are important enough so that one day we might force logging them or throw an exception on startup. -// displayAllErrors: true -// }); +// const log = logFactory(''); function apiKeyError(reason: string) { return `Factory instantiation: ${reason}, api_key must be a non-empty string.`; } diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index 38b08e38..25e1b9dd 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -1,7 +1,7 @@ import { ILogger } from '../../logger/types'; import { IReadinessManager } from '../../readiness/types'; // import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('', { displayAllErrors: true }); +// const log = logFactory(''); export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadinessManager): boolean { if (!readinessManager.isDestroyed()) return true; diff --git a/src/utils/settingsValidation/__tests__/index.spec.ts b/src/utils/settingsValidation/__tests__/index.spec.ts index cf847414..8399060b 100644 --- a/src/utils/settingsValidation/__tests__/index.spec.ts +++ b/src/utils/settingsValidation/__tests__/index.spec.ts @@ -167,7 +167,7 @@ describe('settingsValidation', () => { expect(settings.integrations).toBe(integrationsMock); expect(settings.storage).toBe(storageValidatorResult); - expect(storageValidatorMock).toBeCalledWith(settings.log, settings); + expect(storageValidatorMock).toBeCalledWith(settings); }); test('overwrites integrations with the result of the given integrations validator', () => { diff --git a/src/utils/timeTracker/index.ts b/src/utils/timeTracker/index.ts index fa2dccb3..f6c61b57 100644 --- a/src/utils/timeTracker/index.ts +++ b/src/utils/timeTracker/index.ts @@ -1,7 +1,7 @@ import { uniqueId } from '../lang'; -import { Logger } from '../../logger/index'; import timer from './timer'; import thenable from '../promise/thenable'; +import { ILogger } from '../../logger/types'; // Based on ProducerMetricsCollector and ClientCollector classes interface MetricsCollector { @@ -20,11 +20,6 @@ interface MetricsCollector { [method: string]: (ms: number) => void, } -// logger to be used on this module -const logger = new Logger('[TIME TRACKER]', { - showLevel: false -}); - // Map we will use for storing timers data const timers: Record void), @@ -122,18 +117,19 @@ const TrackerAPI = { * * @param {Promise} promise - The promise we want to attach the callbacks. * @param {string} task - The name of the task. + * @param {ILogger} log - Logger. * @param {number | string} modifier - (optional) The modifier for the task, if any. */ - __attachToPromise(promise: Promise, task: string, collector: false | MetricsCollector, modifier?: number | string) { + __attachToPromise(promise: Promise, task: string, log: ILogger, collector: false | MetricsCollector, modifier?: number | string) { return promise.then(resp => { - this.stop(task, modifier); + this.stop(task, log, modifier); if (collector && collector.count) collector.count(resp.status); return resp; }) .catch(err => { - this.stop(task, modifier); + this.stop(task, log, modifier); if (collector && collector.countException) collector.countException(); @@ -145,11 +141,12 @@ const TrackerAPI = { * there may be multiple SDK instances tracking a "generic" task, making any task non-generic. * * @param {string} task - The task we are starting. + * @param {ILogger} log - Logger. * @param {Object} collectors - The collectors map. * @param {Promise} promise - (optional) The promise we are tracking. * @return {Function | Promise} The stop function for this specific task or the promise received with the callbacks registered. */ - start(task: string, collectors?: Record, promise?: Promise, now?: () => number): Promise | (() => number) { + start(task: string, log: ILogger, collectors?: Record, promise?: Promise, now?: () => number): Promise | (() => number) { const taskUniqueId = uniqueId(); const taskCollector = getCollectorForTask(task, collectors); let result; @@ -157,10 +154,10 @@ const TrackerAPI = { // If we are registering a promise with this task, we should count the status and the exceptions as well // as stopping the task when the promise resolves. Then return the promise if (thenable(promise)) { - result = this.__attachToPromise(promise, task, taskCollector, taskUniqueId); + result = this.__attachToPromise(promise, task, log, taskCollector, taskUniqueId); } else { // If not, we return the stop function, as it will be stopped manually. - result = this.stop.bind(this, task, taskUniqueId); + result = this.stop.bind(this, task, log, taskUniqueId); if (CALLBACKS[task] && !taskCollector) { // and provide a way for a defered setup of the collector, if needed. // @ts-expect-error @@ -197,15 +194,16 @@ const TrackerAPI = { * Stops the tracking of a given task. * * @param {string} task - The task we are starting. + * @param {ILogger} log - Logger. * @param {number | string} modifier - (optional) The modifier for that specific task. */ - stop(task: string, modifier?: number | string) { + stop(task: string, log: ILogger, modifier?: number | string) { const timerName = generateTimerKey(task, modifier); const timerData = timers[timerName]; if (timerData) { // Stop the timer and round result for readability. const et = timerData.timer(); - logger.debug(`[${task}] took ${et}ms to finish.`); + log.debug(`[${task}] took ${et}ms to finish.`); // Check if we have a tracker callback. if (timerData.cb) { From f21f43b9d8cda0b2689bb77f29f9d2b0eb84d320 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 8 Mar 2021 16:05:50 -0300 Subject: [PATCH 16/58] updated InLocalStorage module to use injected log --- src/storages/inLocalStorage/index.ts | 17 ++++++++------- src/types.ts | 2 +- src/utils/settingsValidation/index.ts | 11 +++++----- src/utils/settingsValidation/logger.ts | 30 -------------------------- 4 files changed, 15 insertions(+), 45 deletions(-) delete mode 100644 src/utils/settingsValidation/logger.ts diff --git a/src/storages/inLocalStorage/index.ts b/src/storages/inLocalStorage/index.ts index 0a6574f5..4ca9ee2d 100644 --- a/src/storages/inLocalStorage/index.ts +++ b/src/storages/inLocalStorage/index.ts @@ -9,8 +9,9 @@ import MySegmentsCacheInLocal from './MySegmentsCacheInLocal'; import MySegmentsCacheInMemory from '../inMemory/MySegmentsCacheInMemory'; import SplitsCacheInMemory from '../inMemory/SplitsCacheInMemory'; import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser'; -import { logFactory } from '../../logger/sdkLogger'; -const log = logFactory('splitio-storage:localstorage'); +import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS'; +// import { logFactory } from '../../logger/sdkLogger'; +// const log = logFactory('splitio-storage:localstorage'); export interface InLocalStorageOptions { prefix?: string @@ -21,16 +22,16 @@ export interface InLocalStorageOptions { */ export function InLocalStorage(options: InLocalStorageOptions = {}) { - // Fallback to InMemoryStorage if LocalStorage API is not available - if (!isLocalStorageAvailable()) { - log.warn('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); - return; - } - const prefix = options.prefix ? options.prefix + '.SPLITIO' : 'SPLITIO'; return function InLocalStorageCSFactory(params: IStorageFactoryParams): IStorageSyncCS { + // Fallback to InMemoryStorage if LocalStorage API is not available + if (!isLocalStorageAvailable()) { + params.log.warn('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); + return InMemoryStorageCSFactory(params); + } + const log = params.log; const keys = new KeyBuilderCS(prefix, params.matchingKey as string); const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS; diff --git a/src/types.ts b/src/types.ts index cbec6880..c2093371 100644 --- a/src/types.ts +++ b/src/types.ts @@ -102,7 +102,7 @@ export interface ISettings { ip: string | false hostname: string | false }, - log: ILogger + readonly log: ILogger } /** * Log levels. diff --git a/src/utils/settingsValidation/index.ts b/src/utils/settingsValidation/index.ts index 18fac9ed..a248d69f 100644 --- a/src/utils/settingsValidation/index.ts +++ b/src/utils/settingsValidation/index.ts @@ -1,8 +1,7 @@ import { merge } from '../lang'; -import logger from './logger'; import mode from './mode'; import { validateSplitFilters } from './splitFilters'; -import { API } from '../../logger/sdkLogger'; +import { API, logFactory } from '../../logger/sdkLogger'; import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE } from '../constants'; import validImpressionsMode from './impressionsMode'; import { LogLevel } from '../../types'; @@ -114,6 +113,10 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV // creates a settings object merging base, defaults and config objects. const withDefaults = merge({}, base, defaults, config) as ISettingsInternal; + // ensure a valid logger + const log = logFactory('splitio'); // @ts-ignore + withDefaults.log = log; + // Scheduler periods withDefaults.scheduler.featuresRefreshRate = fromSecondsToMillis(withDefaults.scheduler.featuresRefreshRate); withDefaults.scheduler.segmentsRefreshRate = fromSecondsToMillis(withDefaults.scheduler.segmentsRefreshRate); @@ -127,10 +130,6 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV withDefaults.startup.readyTimeout = fromSecondsToMillis(withDefaults.startup.readyTimeout); withDefaults.startup.eventsFirstPushWindow = fromSecondsToMillis(withDefaults.startup.eventsFirstPushWindow); - // ensure a valid logger - const log = logger(withDefaults); - withDefaults.log = log; - // ensure a valid SDK mode // @ts-ignore withDefaults.mode = mode(withDefaults.core.authorizationKey, withDefaults.mode); diff --git a/src/utils/settingsValidation/logger.ts b/src/utils/settingsValidation/logger.ts deleted file mode 100644 index cfd39fbf..00000000 --- a/src/utils/settingsValidation/logger.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ILogger } from '../../logger/types'; - -const noopLogger = { - debug() { }, - info() { }, - warn() { }, - error() { } -}; - -function isLogger(log: unknown): log is ILogger { - // @ts-ignore - return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function'; -} - -/** - * Validates the `log` (logger) property at config. - * - * @param settings user config object - * @returns the provided logger or a no-op logger if no one is provided - * @throws throws an error if a logger was provided but is invalid - */ -export default function logger(settings: { log: unknown }): ILogger { - const { log } = settings; - - if (!log) return noopLogger; - - if (isLogger(log)) return log; - - throw new Error('The provided `log` value at config is not valid'); -} From b4ea59e7041ef78353d7b52489d54abb13c1af64 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 9 Mar 2021 14:21:43 -0300 Subject: [PATCH 17/58] separete builin from pluggable logger validation --- src/index.ts | 3 - src/logger/__tests__/index.spec.ts | 30 ++--- src/logger/__tests__/sdkLogger.spec.ts | 36 +++--- src/logger/index.ts | 36 +++--- src/logger/sdkLogger.ts | 103 ++++++------------ src/logger/types.ts | 5 + src/sdkFactory/index.ts | 4 +- src/utils/settingsValidation/index.ts | 23 +--- .../logger/builtinLogger.ts | 67 ++++++++++++ .../logger/pluggableLogger.ts | 31 ++++++ src/utils/settingsValidation/types.ts | 2 + 11 files changed, 194 insertions(+), 146 deletions(-) create mode 100644 src/utils/settingsValidation/logger/builtinLogger.ts create mode 100644 src/utils/settingsValidation/logger/pluggableLogger.ts diff --git a/src/index.ts b/src/index.ts index 7cc9b5d7..7abf494f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,6 +22,3 @@ export { evaluateFeature, evaluateFeatures } from './evaluator'; // Utils: export { hash128 } from './utils/murmur3/murmur3_128'; export { hash } from './utils/murmur3/murmur3'; - -// Logger -export { logFactory, API } from './logger/sdkLogger'; diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index 4ab2d782..b973d0ec 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -1,4 +1,5 @@ -import { Logger, LogLevels, setLogLevel, isLogLevelString } from '../index'; +import { LogLevel } from '../../types'; +import { Logger, LogLevels, isLogLevelString } from '../index'; // We'll set this only once. These are the constants we will use for // comparing the LogLevel values. @@ -10,12 +11,6 @@ export const LOG_LEVELS = { NONE: 'NONE' }; -test('SPLIT LOGGER / setLogLevel utility function', () => { - expect(typeof setLogLevel).toBe('function'); // setLogLevel should be a function - expect(setLogLevel).not.toThrow(); // Calling setLogLevel should not throw an error. - -}); - test('SPLIT LOGGER / isLogLevelString utility function', () => { expect(typeof isLogLevelString).toBe('function'); // isLogLevelString should be a function expect(isLogLevelString(LOG_LEVELS.DEBUG)).toBe(true); // Calling isLogLevelString should return true with a LOG_LEVELS value @@ -32,18 +27,20 @@ test('SPLIT LOGGER / LogLevels exposed mappings', () => { test('SPLIT LOGGER / Logger class shape', () => { expect(typeof Logger).toBe('function'); // Logger should be a class we can instantiate. - const logger = new Logger('test-category', {}); + const logger = new Logger('test-category'); expect(typeof logger.debug).toBe('function'); // instance.debug should be a method. expect(typeof logger.info).toBe('function'); // instance.info should be a method. expect(typeof logger.warn).toBe('function'); // instance.warn should be a method. expect(typeof logger.error).toBe('function'); // instance.error should be a method. + expect(typeof logger.options.logLevel).toBe('string'); // instance.options.logLevel should be a string. + expect(typeof logger.options.showLevel).toBe('boolean'); // instance.options.showLevel should be a boolean. }); const LOG_LEVELS_IN_ORDER = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE']; /* Utility function to avoid repeating too much code */ -function testLogLevels(levelToTest: string) { +function testLogLevels(levelToTest: LogLevel) { // Builds the expected message. const buildExpectedMessage = (lvl: string, category: string, msg: string, showLevel?: boolean) => { let res = ''; @@ -57,24 +54,21 @@ function testLogLevels(levelToTest: string) { const consoleLogSpy = jest.spyOn(global.console, 'log'); // Runs the suite with the given value for showLevel option. - const runTests = (showLevel?: boolean, displayAllErrors?: boolean) => { + const runTests = (showLevel?: boolean) => { let logLevelLogsCounter = 0; let testForNoLog = false; const logMethod = levelToTest.toLowerCase(); - const logCategory = `test-category-${logMethod}${displayAllErrors ? 'displayAllErrors' : ''}`; + const logCategory = `test-category-${logMethod}`; const instance = new Logger(logCategory, { - showLevel, displayAllErrors + showLevel }); LOG_LEVELS_IN_ORDER.forEach((logLevel, i) => { - const logMsg = `Test log for level ${levelToTest} (${displayAllErrors ? 'But all errors are configured to display' : 'Errors not forced to display'}) with showLevel: ${showLevel} ${logLevelLogsCounter}`; + const logMsg = `Test log for level ${levelToTest} with showLevel: ${showLevel} ${logLevelLogsCounter}`; const expectedMessage = buildExpectedMessage(levelToTest, logCategory, logMsg, showLevel); - // Log error should always be visible. - if (logMethod === LOG_LEVELS.ERROR.toLowerCase() && displayAllErrors) testForNoLog = false; - // Set the logLevel for this iteration. - setLogLevel(LogLevels[logLevel]); + instance.options.logLevel = LogLevels[logLevel]; // Call the method // @ts-ignore instance[logMethod](logMsg); @@ -95,10 +89,8 @@ function testLogLevels(levelToTest: string) { // Show logLevel runTests(true); - runTests(true, true); // Hide logLevel runTests(false); - runTests(false, true); // Restore spied object. consoleLogSpy.mockRestore(); diff --git a/src/logger/__tests__/sdkLogger.spec.ts b/src/logger/__tests__/sdkLogger.spec.ts index d607409c..ce716e71 100644 --- a/src/logger/__tests__/sdkLogger.spec.ts +++ b/src/logger/__tests__/sdkLogger.spec.ts @@ -1,22 +1,30 @@ -import { logFactory, API } from '../sdkLogger'; -import { Logger } from '../index'; -import { LOG_LEVELS } from './index.spec'; +import { createLoggerAPI } from '../sdkLogger'; +import { Logger, LogLevels } from '../index'; -test('SPLIT SDK LOGGER FACTORY / methods and props', () => { +test('createLoggerAPI / methods and props', () => { + const logger = new Logger('category', {}); - expect(typeof logFactory).toBe('function'); // Importing the module should return a function. + expect(typeof createLoggerAPI).toBe('function'); // Importing the module should return a function. - expect(typeof API).toBe('object'); // Our logger should expose an API object. - expect(typeof API.enable).toBe('function'); // API object should have enable method. - expect(typeof API.disable).toBe('function'); // API object should have disable method. - expect(typeof API.setLogLevel).toBe('function'); // API object should have setLogLevel method. - expect(API.LogLevel).toEqual(LOG_LEVELS); // API object should have LogLevel prop including all available levels. + const loggerAPI = createLoggerAPI(logger); -}); + expect(typeof loggerAPI).toBe('object'); // Our logger should expose an API object. + + expect(typeof loggerAPI.setLogLevel).toBe('function'); // API object should have setLogLevel method. + loggerAPI.setLogLevel('INFO'); + expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel should update the log level. + // @ts-ignore + loggerAPI.setLogLevel('warn'); + expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel with an invalid value should not update the log level. + + expect(typeof loggerAPI.enable).toBe('function'); // API object should have enable method. + loggerAPI.enable(); + expect(logger.options.logLevel).toBe('DEBUG'); // calling enable should update logger log level to DEBUG. -test('SPLIT SDK LOGGER FACTORY / create factory returned instance', () => { - const logger = logFactory('category', {}); + expect(typeof loggerAPI.disable).toBe('function'); // API object should have disable method. + loggerAPI.disable(); + expect(logger.options.logLevel).toBe('NONE'); // calling disable should update logger log level to NONE. - expect(logger instanceof Logger).toBe(true); // Our logger should expose an API object. + expect(loggerAPI.LogLevel).toEqual(LogLevels); // API object should have LogLevel prop including all available levels. }); diff --git a/src/logger/index.ts b/src/logger/index.ts index e7da05af..f7fd7959 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -11,57 +11,49 @@ export const LogLevels: { [level: string]: LogLevel } = { NONE: 'NONE' }; -// DEBUG is the default. The log level is not specific to an SDK instance. -let globalLogLevel = LogLevels.DEBUG; - -export function setLogLevel(level: LogLevel) { - globalLogLevel = level; -} - export function isLogLevelString(str: string): str is LogLevel { return !!find(LogLevels, (lvl: string) => str === lvl); } const defaultOptions = { + logLevel: LogLevels.NONE, showLevel: true, }; export class Logger implements ILogger { private category: string; - private options: Required; + public options: Required; - constructor(category: string, options: ILoggerOptions) { + constructor(category: string, options?: ILoggerOptions) { this.category = category; this.options = objectAssign({}, defaultOptions, options); } debug(msg: string) { - if (this._shouldLog(LogLevels.DEBUG)) - this._log(LogLevels.DEBUG, msg); + this._log(LogLevels.DEBUG, msg); } info(msg: string) { - if (this._shouldLog(LogLevels.INFO)) - this._log(LogLevels.INFO, msg); + this._log(LogLevels.INFO, msg); } warn(msg: string) { - if (this._shouldLog(LogLevels.WARN)) - this._log(LogLevels.WARN, msg); + this._log(LogLevels.WARN, msg); } error(msg: string) { - if (this._shouldLog(LogLevels.ERROR)) - this._log(LogLevels.ERROR, msg); + this._log(LogLevels.ERROR, msg); } - _log(level: string, text: string) { - const formattedText = this._generateLogMessage(level, text); + _log(level: LogLevel, text: string) { + if (this._shouldLog(level)) { + const formattedText = this._generateLogMessage(level, text); - console.log(formattedText); + console.log(formattedText); + } } - _generateLogMessage(level: string, text: string) { + _generateLogMessage(level: LogLevel, text: string) { const textPre = ' => '; let result = ''; @@ -77,7 +69,7 @@ export class Logger implements ILogger { } _shouldLog(level: LogLevel) { - const logLevel = globalLogLevel; + const logLevel = this.options.logLevel; const levels = Object.keys(LogLevels).map((f) => LogLevels[f as keyof typeof LogLevels]); const index = levels.indexOf(level); // What's the index of what it's trying to check if it should log const levelIdx = levels.indexOf(logLevel); // What's the current log level index. diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index af11fdda..4c98269f 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -1,78 +1,47 @@ -/** - * This file defines the logger interface and default options for the SDKs, not necessarily for the Logger as it's own. - */ -import { ILoggerOptions } from './types'; -import { Logger, LogLevels, setLogLevel, isLogLevelString } from '.'; -import { isLocalStorageAvailable } from '../utils/env/isLocalStorageAvailable'; -import { isNode } from '../utils/env/isNode'; -import { merge } from '../utils/lang'; +import { LogLevels, isLogLevelString } from './index'; import { ILoggerAPI } from '../types'; +import { ILogger } from './types'; +// const log = logFactory('splitio-utils:logger'); -// @TODO when integrating with other packages, find the best way to update LoggerOption defaults per package (node, evaluator, etc.) -const defaultOptions: ILoggerOptions = { - showLevel: true, -}; - -// @TODO when integrating with other packages, find the best way to handle initial state per package/environment -const LS_KEY = 'splitio_debug'; -const ENV_VAR_KEY = 'SPLITIO_DEBUG'; /** - * Logger initial debug level, that is disabled ('NONE') by default. - * Acceptable values are: 'DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'. - * Other acceptable values are 'on', 'enable' and 'enabled', which are equivalent to 'DEBUG'. - * Any other string value is equivalent to disable. + * The public Logger utility API exposed via SplitFactory, used to update the log level. + * + * @param log the factory logger instance to handle */ -const initialState = String( - // eslint-disable-next-line no-undef - isNode ? process.env[ENV_VAR_KEY] : isLocalStorageAvailable() ? localStorage.getItem(LS_KEY) : '' -); - -// we expose the logger instance creator -export const logFactory = (namespace: string, options = {}) => new Logger(namespace, merge(options, defaultOptions)); +export function createLoggerAPI(log: ILogger): ILoggerAPI { -const ownLog = logFactory('splitio-utils:logger'); - -/** - * The public Logger utility API exposed via SplitFactory. - */ -export const API: ILoggerAPI = { - /** - * Enables all the logs. - */ - enable() { - setLogLevel(LogLevels.DEBUG); - }, - /** - * Sets a custom log Level for the SDK. - * @param {string} logLevel - Custom LogLevel value. - */ - setLogLevel(logLevel: string) { + function setLogLevel(logLevel: string) { if (isLogLevelString(logLevel)) { - setLogLevel(logLevel); + log.options.logLevel = logLevel; } else { - ownLog.error('Invalid Log Level - No changes to the logs will be applied.'); + log.error('Invalid Log Level - No changes to the logs will be applied.'); } - }, - /** - * Disables all the log levels. - */ - disable() { - // Disabling is equal logLevel none - setLogLevel(LogLevels.NONE); - }, - /** - * Exposed for usage with setLogLevel - */ - LogLevel: LogLevels -}; + } + + return { + /** + * Enables all the logs. + */ + enable() { + setLogLevel(LogLevels.DEBUG); + }, + /** + * Sets a custom log Level for the SDK. + * @param {string} logLevel - Custom LogLevel value. + */ + setLogLevel, + /** + * Disables all the log levels. + */ + disable() { + // Disabling is equal logLevel none + setLogLevel(LogLevels.NONE); + }, + /** + * Exposed for usage with setLogLevel + */ + LogLevel: LogLevels + }; -// Kept to avoid a breaking change ('on', 'enable' and 'enabled' are equivalent) -if (/^(enabled?|on)/i.test(initialState)) { - API.enable(); -} else if (isLogLevelString(initialState)) { - API.setLogLevel(initialState); -} else { - // By default it starts disabled. - API.disable(); } diff --git a/src/logger/types.ts b/src/logger/types.ts index 46a59273..b8f08302 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -1,8 +1,13 @@ +import { LogLevel } from '../types'; + export interface ILoggerOptions { + logLevel?: LogLevel, showLevel?: boolean, } export interface ILogger { + options: ILoggerOptions + debug(msg: string): void info(msg: string): void diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 2288e95b..652fcca8 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -9,7 +9,7 @@ import { ISplitApi } from '../services/types'; import { getMatching } from '../utils/key'; import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; -import { API } from '../logger/sdkLogger'; +import { createLoggerAPI } from '../logger/sdkLogger'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); @@ -94,7 +94,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. }, // Logger wrapper API - Logger: API, + Logger: createLoggerAPI(settings.log), settings, }; diff --git a/src/utils/settingsValidation/index.ts b/src/utils/settingsValidation/index.ts index a248d69f..19e7d177 100644 --- a/src/utils/settingsValidation/index.ts +++ b/src/utils/settingsValidation/index.ts @@ -1,10 +1,8 @@ import { merge } from '../lang'; import mode from './mode'; import { validateSplitFilters } from './splitFilters'; -import { API, logFactory } from '../../logger/sdkLogger'; import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE } from '../constants'; import validImpressionsMode from './impressionsMode'; -import { LogLevel } from '../../types'; import { ISettingsInternal, ISettingsValidationParams } from './types'; const base = { @@ -88,18 +86,6 @@ function fromSecondsToMillis(n: number) { return Math.round(n * 1000); } -function setupLogger(debugValue: any) { - if (typeof debugValue === 'boolean') { - if (debugValue) { - API.enable(); - } else { - API.disable(); - } - } else if (typeof debugValue === 'string') { - API.setLogLevel(debugValue as LogLevel); - } -} - /** * Validates the given config and use it to build a settings object. * @@ -108,13 +94,14 @@ function setupLogger(debugValue: any) { */ export function settingsValidation(config: unknown, validationParams: ISettingsValidationParams) { - const { defaults, runtime, storage, integrations } = validationParams; + const { defaults, runtime, storage, integrations, logger } = validationParams; // creates a settings object merging base, defaults and config objects. const withDefaults = merge({}, base, defaults, config) as ISettingsInternal; - // ensure a valid logger - const log = logFactory('splitio'); // @ts-ignore + // ensure a valid logger. + // First thing to validate, since other validators might use the logger. + const log = logger(withDefaults); // @ts-ignore withDefaults.log = log; // Scheduler periods @@ -138,8 +125,6 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV // @ts-ignore if (storage) withDefaults.storage = storage(withDefaults); - setupLogger(withDefaults.debug); - // Although `key` is mandatory according to TS declaration files, it can be omitted in LOCALHOST mode. In that case, the value `localhost_key` is used. if (withDefaults.mode === LOCALHOST_MODE && withDefaults.core.key === undefined) { withDefaults.core.key = 'localhost_key'; diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts new file mode 100644 index 00000000..51a993e3 --- /dev/null +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -0,0 +1,67 @@ +import { isLogLevelString, Logger, LogLevels } from '../../../logger'; +import { ILogger } from '../../../logger/types'; +import { LogLevel } from '../../../types'; +import { isLocalStorageAvailable } from '../../env/isLocalStorageAvailable'; +import { isNode } from '../../env/isNode'; + +// @TODO when integrating with other packages, find the best way to handle initial state per environment +const LS_KEY = 'splitio_debug'; +const ENV_VAR_KEY = 'SPLITIO_DEBUG'; + +/** + * Logger initial debug level, that is disabled ('NONE') by default. + * Acceptable values are: 'DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'. + * Other acceptable values are 'on', 'enable' and 'enabled', which are equivalent to 'DEBUG'. + * Any other string value is equivalent to disable. + */ +const initialState = String( + // eslint-disable-next-line no-undef + isNode ? process.env[ENV_VAR_KEY] : isLocalStorageAvailable() ? localStorage.getItem(LS_KEY) : '' +); + + +// By default it starts disabled. +let initialLogLevel = LogLevels.NONE; + +// Kept to avoid a breaking change ('on', 'enable' and 'enabled' are equivalent) +if (/^(enabled?|on)/i.test(initialState)) { + initialLogLevel = LogLevels.DEBUG; +} else if (isLogLevelString(initialState)) { + initialLogLevel = initialState; +} + +// returns the LogLevel for the given debugValue or undefined if it is invalid. +// debugValue must be a boolean or LogLevel string. +export function getLogLevel(debugValue: unknown): LogLevel | undefined { + if (typeof debugValue === 'boolean') { + if (debugValue) { + return LogLevels.DEBUG; + } else { + return LogLevels.NONE; + } + } else if (typeof debugValue === 'string' && isLogLevelString(debugValue)) { + return debugValue; + } else { + return undefined; + } +} + +/** + * Validates the `debug` property at config and use it to set the log level. + * + * @param settings user config object + * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. + */ +export function validateLogger(settings: { debug: unknown} ): ILogger { + + const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; + + const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }); + + // logs error if the provided settings debug value is invalid + if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); + + return log; +} + + diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts new file mode 100644 index 00000000..52e38712 --- /dev/null +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -0,0 +1,31 @@ +import { ILogger } from '../../../logger/types'; + +const noopLogger: ILogger = { + options: { logLevel: 'NONE' }, + debug() { }, + info() { }, + warn() { }, + error() { } +}; + +function isLogger(log: unknown): log is ILogger { + // @ts-ignore + return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function'; +} + +/** + * Validates the `log` (logger) property at config. + * + * @param settings user config object + * @returns the provided logger or a no-op logger if no one is provided + * @throws throws an error if a logger was provided but is invalid + */ +export function validateLogger(settings: { debug: unknown }): ILogger { + const { debug } = settings; + + if (!debug) return noopLogger; + + if (isLogger(debug)) return debug; + + throw new Error('The provided `debug` value at config is not valid'); +} diff --git a/src/utils/settingsValidation/types.ts b/src/utils/settingsValidation/types.ts index d2845582..5a07379d 100644 --- a/src/utils/settingsValidation/types.ts +++ b/src/utils/settingsValidation/types.ts @@ -15,6 +15,8 @@ export interface ISettingsValidationParams { storage?: (settings: ISettings) => ISettings['storage'], /** Integrations validator */ integrations?: (settings: ISettings) => ISettings['integrations'], + /** Logger validator */ + logger: (settings: ISettings) => ISettings['log'], } /** From cbda12d1ce7d1be32343b139e29f1be76c4dc19e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 9 Mar 2021 16:59:19 -0300 Subject: [PATCH 18/58] updated UTs --- src/logger/__tests__/index.spec.ts | 15 ++------ .../inLocalStorage/__tests__/index.spec.ts | 37 ++++++++++++++++--- .../SSEHandler/__tests__/index.spec.ts | 2 +- src/utils/timeTracker/__tests__/index.spec.ts | 17 +++++---- 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index 4ab2d782..9ca544c7 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -57,22 +57,17 @@ function testLogLevels(levelToTest: string) { const consoleLogSpy = jest.spyOn(global.console, 'log'); // Runs the suite with the given value for showLevel option. - const runTests = (showLevel?: boolean, displayAllErrors?: boolean) => { + const runTests = (showLevel?: boolean) => { let logLevelLogsCounter = 0; let testForNoLog = false; const logMethod = levelToTest.toLowerCase(); - const logCategory = `test-category-${logMethod}${displayAllErrors ? 'displayAllErrors' : ''}`; - const instance = new Logger(logCategory, { - showLevel, displayAllErrors - }); + const logCategory = `test-category-${logMethod}`; + const instance = new Logger(logCategory, { showLevel }); LOG_LEVELS_IN_ORDER.forEach((logLevel, i) => { - const logMsg = `Test log for level ${levelToTest} (${displayAllErrors ? 'But all errors are configured to display' : 'Errors not forced to display'}) with showLevel: ${showLevel} ${logLevelLogsCounter}`; + const logMsg = `Test log for level ${levelToTest} with showLevel: ${showLevel} ${logLevelLogsCounter}`; const expectedMessage = buildExpectedMessage(levelToTest, logCategory, logMsg, showLevel); - // Log error should always be visible. - if (logMethod === LOG_LEVELS.ERROR.toLowerCase() && displayAllErrors) testForNoLog = false; - // Set the logLevel for this iteration. setLogLevel(LogLevels[logLevel]); // Call the method @@ -95,10 +90,8 @@ function testLogLevels(levelToTest: string) { // Show logLevel runTests(true); - runTests(true, true); // Hide logLevel runTests(false); - runTests(false, true); // Restore spied object. consoleLogSpy.mockRestore(); diff --git a/src/storages/inLocalStorage/__tests__/index.spec.ts b/src/storages/inLocalStorage/__tests__/index.spec.ts index 163301b0..131f2eff 100644 --- a/src/storages/inLocalStorage/__tests__/index.spec.ts +++ b/src/storages/inLocalStorage/__tests__/index.spec.ts @@ -1,23 +1,48 @@ +// Mocks +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; +import { IStorageFactoryParams } from '../../types'; +const fakeInMemoryStorage = 'fakeStorage'; +const fakeInMemoryStorageFactory = jest.fn(() => fakeInMemoryStorage); +jest.mock('../../inMemory/InMemoryStorageCS', () => { + return { + InMemoryStorageCSFactory: fakeInMemoryStorageFactory + }; +}); + +// Test target import { InLocalStorage } from '../index'; describe('IN LOCAL STORAGE', () => { - test('return undefined if LocalStorage API is not available', () => { + // @ts-ignore + const internalSdkParams: IStorageFactoryParams = { log: loggerMock }; + + afterEach(() => { + fakeInMemoryStorageFactory.mockClear(); + }); + + test('calls InMemoryStorage factory if LocalStorage API is not available', () => { const originalLocalStorage = Object.getOwnPropertyDescriptor(global, 'localStorage'); Object.defineProperty(global, 'localStorage', {}); // delete global localStorage property - const storage = InLocalStorage({ prefix: 'prefix' }); - expect(storage).toBe(undefined); + const storageFactory = InLocalStorage({ prefix: 'prefix' }); + const storage = storageFactory(internalSdkParams); + + expect(fakeInMemoryStorageFactory).toBeCalledWith(internalSdkParams); // calls InMemoryStorage factory + expect(storage).toBe(fakeInMemoryStorage); Object.defineProperty(global, 'localStorage', originalLocalStorage as PropertyDescriptor); // restore original localStorage }); - test('return a new storage if LocalStorage API is available', () => { + test('calls its own storage factory if LocalStorage API is available', () => { + + const storageFactory = InLocalStorage({ prefix: 'prefix' }); + const storage = storageFactory(internalSdkParams); - const storage = InLocalStorage({ prefix: 'prefix' }); - expect(typeof storage).toBe('function'); + expect(typeof storage).toBe('object'); + expect(fakeInMemoryStorageFactory).not.toBeCalled(); // doesn't call InMemoryStorage factory }); diff --git a/src/sync/streaming/SSEHandler/__tests__/index.spec.ts b/src/sync/streaming/SSEHandler/__tests__/index.spec.ts index 0366037a..a7b855af 100644 --- a/src/sync/streaming/SSEHandler/__tests__/index.spec.ts +++ b/src/sync/streaming/SSEHandler/__tests__/index.spec.ts @@ -72,7 +72,7 @@ test('`handleOpen` and `handlerMessage` for OCCUPANCY notifications (Notificatio test('`handlerMessage` for CONTROL notifications (NotificationKeeper)', () => { pushEmitter.emit.mockClear(); - const sseHandler = SSEHandlerFactory(pushEmitter); + const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); sseHandler.handleOpen(); // CONTROL messages diff --git a/src/utils/timeTracker/__tests__/index.spec.ts b/src/utils/timeTracker/__tests__/index.spec.ts index 7ce7fa84..45fcf05e 100644 --- a/src/utils/timeTracker/__tests__/index.spec.ts +++ b/src/utils/timeTracker/__tests__/index.spec.ts @@ -1,5 +1,6 @@ import timer from '../timer'; import tracker from '../index'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('TIMER / should count the time between two tasks', (done) => { const timerDuration = Math.floor(Math.random() * 1000); // In millis @@ -26,9 +27,9 @@ describe('TIME TRACKER', () => { const promise = new Promise(res => { setTimeout(res, 1000); }); - const startNormal = tracker.start(tracker.TaskNames.SDK_READY); - const startNormalFake = tracker.start('fakeTask3'); - const startWithPromise = tracker.start('fakeTask4', undefined, promise) as Promise; + const startNormal = tracker.start(tracker.TaskNames.SDK_READY, loggerMock); + const startNormalFake = tracker.start('fakeTask3', loggerMock); + const startWithPromise = tracker.start('fakeTask4', loggerMock, undefined, promise) as Promise; expect(typeof startNormal).toBe('function'); // If we call start without a promise, it will return the stop function, // @ts-expect-error @@ -39,14 +40,14 @@ describe('TIME TRACKER', () => { }); test('stop() / should stop the timer and return the time, if any', () => { - tracker.start('test_task'); + tracker.start('test_task', loggerMock); // creating two tasks with the same task name - const stopFromStart = tracker.start('fakeTask5') as () => number; - const stopFromStart2 = tracker.start('fakeTask5') as () => number; + const stopFromStart = tracker.start('fakeTask5', loggerMock) as () => number; + const stopFromStart2 = tracker.start('fakeTask5', loggerMock) as () => number; - const stopNotExistentTask = tracker.stop('not_existent'); - const stopNotExistentTaskAndModifier = tracker.stop('test_task', 'mod'); + const stopNotExistentTask = tracker.stop('not_existent', loggerMock); + const stopNotExistentTaskAndModifier = tracker.stop('test_task', loggerMock, 'mod'); expect(typeof stopNotExistentTask).toBe('undefined'); // If we try to stop a timer that does not exist, we get undefined. expect(typeof stopNotExistentTaskAndModifier).toBe('undefined'); // If we try to stop a timer that does not exist, we get undefined. From 2e46c0ceec5498e5f48725f7ae16645c454fdab4 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 9 Mar 2021 17:36:17 -0300 Subject: [PATCH 19/58] updated UTs --- src/logger/__tests__/sdkLogger.mock.ts | 3 +++ src/sdkFactory/__tests__/index.spec.ts | 9 +++++++-- src/utils/settingsValidation/__tests__/index.spec.ts | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/logger/__tests__/sdkLogger.mock.ts b/src/logger/__tests__/sdkLogger.mock.ts index 542c6b35..d8f895d8 100644 --- a/src/logger/__tests__/sdkLogger.mock.ts +++ b/src/logger/__tests__/sdkLogger.mock.ts @@ -1,8 +1,11 @@ +import { ILoggerOptions } from '../types'; + export const loggerMock = { warn: jest.fn(), error: jest.fn(), debug: jest.fn(), info: jest.fn(), + options: { logLevel: 'NONE', showLevel: true } as ILoggerOptions }; export function mockClear() { diff --git a/src/sdkFactory/__tests__/index.spec.ts b/src/sdkFactory/__tests__/index.spec.ts index 4ba94a97..3e758f68 100644 --- a/src/sdkFactory/__tests__/index.spec.ts +++ b/src/sdkFactory/__tests__/index.spec.ts @@ -1,6 +1,5 @@ import { ISdkFactoryParams } from '../types'; import { sdkFactory } from '../index'; -import { API } from '../../logger/sdkLogger'; import { fullSettings } from '../../utils/settingsValidation/__tests__/settings.mocks'; import { SplitIO } from '../../types'; import EventEmitter from '../../utils/MinEvents'; @@ -14,6 +13,12 @@ const mockStorage = { events: jest.fn(), impressions: jest.fn() }; +const loggerApiMock = 'loggerApi'; +jest.mock('../../logger/sdkLogger', () => { + return { + createLoggerAPI: () => loggerApiMock + }; +}); // IAsyncSDK, minimal params const paramsForAsyncSDK = { @@ -48,7 +53,7 @@ const fullParamsForSyncSDK = { /** End Mocks */ function assertSdkApi(sdk: SplitIO.IAsyncSDK | SplitIO.ISDK | SplitIO.ICsSDK, params: any) { - expect(sdk.Logger).toBe(API); + expect(sdk.Logger).toBe(loggerApiMock); expect(sdk.settings).toBe(params.settings); expect(sdk.client).toBe(params.sdkClientMethodFactory.mock.results[0].value); expect(sdk.manager()).toBe(params.sdkManagerFactory.mock.results[0].value); diff --git a/src/utils/settingsValidation/__tests__/index.spec.ts b/src/utils/settingsValidation/__tests__/index.spec.ts index 8399060b..be0087b5 100644 --- a/src/utils/settingsValidation/__tests__/index.spec.ts +++ b/src/utils/settingsValidation/__tests__/index.spec.ts @@ -1,4 +1,5 @@ import _ from 'lodash'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { ISettings } from '../../../types'; import { OPTIMIZED, DEBUG } from '../../constants'; @@ -17,7 +18,8 @@ const minimalSettingsParams = { }, version: 'javascript-test', }, - runtime: () => ({ ip: false, hostname: false } as ISettings['runtime']) + runtime: () => ({ ip: false, hostname: false } as ISettings['runtime']), + logger: () => (loggerMock as ISettings['log']) }; describe('settingsValidation', () => { From c955dbf415eedee053e79f68d05c783362241719 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 10 Mar 2021 14:03:00 -0300 Subject: [PATCH 20/58] polishing --- src/logger/__tests__/index.spec.ts | 2 +- src/logger/debugLogger.ts | 15 --------------- src/logger/errorLogger.ts | 12 ------------ src/logger/index.ts | 2 +- src/logger/infoLogger.ts | 14 -------------- src/logger/warnLogger.ts | 13 ------------- 6 files changed, 2 insertions(+), 56 deletions(-) delete mode 100644 src/logger/debugLogger.ts delete mode 100644 src/logger/errorLogger.ts delete mode 100644 src/logger/infoLogger.ts delete mode 100644 src/logger/warnLogger.ts diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index 019b4796..e9f8ffdc 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -38,7 +38,7 @@ test('SPLIT LOGGER / Logger class shape', () => { }); -const LOG_LEVELS_IN_ORDER: LogLevel[] = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE']; +const LOG_LEVELS_IN_ORDER = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE']; /* Utility function to avoid repeating too much code */ function testLogLevels(levelToTest: LogLevel) { // Builds the expected message. diff --git a/src/logger/debugLogger.ts b/src/logger/debugLogger.ts deleted file mode 100644 index b9ae4993..00000000 --- a/src/logger/debugLogger.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Logger } from '.'; -import { codesDebug } from './codesDebug'; -import { codesError } from './codesError'; -import { codesInfo } from './codesInfo'; -import { codesWarn } from './codesWarn'; - -const codes = { - ERROR: codesError, - WARN: codesWarn, - INFO: codesInfo, - DEBUG: codesDebug, - NONE: [], -}; - -export const debugLogger = new Logger(undefined, undefined, codes); diff --git a/src/logger/errorLogger.ts b/src/logger/errorLogger.ts deleted file mode 100644 index a9d1ada7..00000000 --- a/src/logger/errorLogger.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Logger } from '.'; -import { codesError } from './codesError'; - -const codes = { - ERROR: codesError, - WARN: [], - INFO: [], - DEBUG: [], - NONE: [], -}; - -export const errorLogger = new Logger(undefined, undefined, codes); diff --git a/src/logger/index.ts b/src/logger/index.ts index c6a79c0b..9f592b79 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -4,7 +4,7 @@ import { find } from '../utils/lang'; import { LogLevel } from '../types'; import { IMap, _Map } from '../utils/lang/maps'; -export const LogLevels: { [level in LogLevel]: LogLevel } = { +export const LogLevels: { [level: string]: LogLevel } = { DEBUG: 'DEBUG', INFO: 'INFO', WARN: 'WARN', diff --git a/src/logger/infoLogger.ts b/src/logger/infoLogger.ts deleted file mode 100644 index c4d06d9b..00000000 --- a/src/logger/infoLogger.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Logger } from '.'; -import { codesError } from './codesError'; -import { codesInfo } from './codesInfo'; -import { codesWarn } from './codesWarn'; - -const codes = { - ERROR: codesError, - WARN: codesWarn, - INFO: codesInfo, - DEBUG: [], - NONE: [], -}; - -export const infoLogger = new Logger(undefined, undefined, codes); diff --git a/src/logger/warnLogger.ts b/src/logger/warnLogger.ts deleted file mode 100644 index 3f28a03a..00000000 --- a/src/logger/warnLogger.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Logger } from '.'; -import { codesError } from './codesError'; -import { codesWarn } from './codesWarn'; - -const codes = { - ERROR: codesError, - WARN: codesWarn, - INFO: [], - DEBUG: [], - NONE: [], -}; - -export const warnLogger = new Logger(undefined, undefined, codes); From dabadb258d516067eb1636729aacf01b668725b7 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 10 Mar 2021 17:51:12 -0300 Subject: [PATCH 21/58] putting back a commented log --- src/evaluator/condition/__tests__/engineUtils.spec.ts | 5 +++-- src/evaluator/condition/engineUtils.ts | 5 +++-- src/evaluator/condition/index.ts | 11 ++++++----- src/evaluator/parser/index.ts | 1 + 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/evaluator/condition/__tests__/engineUtils.spec.ts b/src/evaluator/condition/__tests__/engineUtils.spec.ts index ce249244..0f1a6d87 100644 --- a/src/evaluator/condition/__tests__/engineUtils.spec.ts +++ b/src/evaluator/condition/__tests__/engineUtils.spec.ts @@ -1,5 +1,6 @@ import * as engineUtils from '../engineUtils'; import Treatments from '../../treatments'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; const treatmentsMock = Treatments.parse([{ treatment: 'on', @@ -15,7 +16,7 @@ test('ENGINE / should always evaluate to "off"', () => { let startTime = Date.now(); - expect(engineUtils.getTreatment(bucketingKey, seed, treatmentsMock) === 'off').toBe(true); // treatment should be 'off' + expect(engineUtils.getTreatment(loggerMock, bucketingKey, seed, treatmentsMock) === 'off').toBe(true); // treatment should be 'off' let endTime = Date.now(); @@ -29,7 +30,7 @@ test('ENGINE / should always evaluate to "on"', () => { let startTime = Date.now(); - expect(engineUtils.getTreatment(bucketingKey, seed, treatmentsMock) === 'on').toBe(true); // treatment should be 'on' + expect(engineUtils.getTreatment(loggerMock, bucketingKey, seed, treatmentsMock) === 'on').toBe(true); // treatment should be 'on' let endTime = Date.now(); diff --git a/src/evaluator/condition/engineUtils.ts b/src/evaluator/condition/engineUtils.ts index 78cbac09..be0b4fc9 100644 --- a/src/evaluator/condition/engineUtils.ts +++ b/src/evaluator/condition/engineUtils.ts @@ -1,3 +1,4 @@ +import { ILogger } from '../../logger/types'; import { bucket } from '../../utils/murmur3/murmur3'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine'); @@ -5,12 +6,12 @@ import { bucket } from '../../utils/murmur3/murmur3'; /** * Get the treatment name given a key, a seed, and the percentage of each treatment. */ -export function getTreatment(key: string, seed: number, treatments: { getTreatmentFor: (x: number) => string }) { +export function getTreatment(log: ILogger, key: string, seed: number, treatments: { getTreatmentFor: (x: number) => string }) { const _bucket = bucket(key, seed); const treatment = treatments.getTreatmentFor(_bucket); - // log.debug(`[engine] using algo 'murmur' bucket ${_bucket} for key ${key} using seed ${seed} - treatment ${treatment}`); + log.debug(`[engine] using algo 'murmur' bucket ${_bucket} for key ${key} using seed ${seed} - treatment ${treatment}`); return treatment; } diff --git a/src/evaluator/condition/index.ts b/src/evaluator/condition/index.ts index f0ab2658..542617ea 100644 --- a/src/evaluator/condition/index.ts +++ b/src/evaluator/condition/index.ts @@ -4,11 +4,12 @@ import * as LabelsConstants from '../../utils/labels'; import { MaybeThenable } from '../../dtos/types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; import { SplitIO } from '../../types'; +import { ILogger } from '../../logger/types'; // Build Evaluation object if and only if matchingResult is true -function match(matchingResult: boolean, bucketingKey: string | undefined, seed: number, treatments: { getTreatmentFor: (x: number) => string }, label: string): IEvaluation | undefined { +function match(log: ILogger, matchingResult: boolean, bucketingKey: string | undefined, seed: number, treatments: { getTreatmentFor: (x: number) => string }, label: string): IEvaluation | undefined { if (matchingResult) { - const treatment = getTreatment(bucketingKey as string, seed, treatments); + const treatment = getTreatment(log, bucketingKey as string, seed, treatments); return { treatment, @@ -21,7 +22,7 @@ function match(matchingResult: boolean, bucketingKey: string | undefined, seed: } // Condition factory -export default function conditionContext(matcherEvaluator: (...args: any) => MaybeThenable, treatments: { getTreatmentFor: (x: number) => string }, label: string, conditionType: 'ROLLOUT' | 'WHITELIST'): IEvaluator { +export default function conditionContext(log: ILogger, matcherEvaluator: (...args: any) => MaybeThenable, treatments: { getTreatmentFor: (x: number) => string }, label: string, conditionType: 'ROLLOUT' | 'WHITELIST'): IEvaluator { return function conditionEvaluator(key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) { @@ -40,10 +41,10 @@ export default function conditionContext(matcherEvaluator: (...args: any) => May const matches = matcherEvaluator(key, attributes, splitEvaluator); if (thenable(matches)) { - return matches.then(result => match(result, (key as SplitIO.SplitKeyObject).bucketingKey, seed, treatments, label)); + return matches.then(result => match(log, result, (key as SplitIO.SplitKeyObject).bucketingKey, seed, treatments, label)); } - return match(matches, (key as SplitIO.SplitKeyObject).bucketingKey, seed, treatments, label); + return match(log, matches, (key as SplitIO.SplitKeyObject).bucketingKey, seed, treatments, label); }; } diff --git a/src/evaluator/parser/index.ts b/src/evaluator/parser/index.ts index 41a03867..d2187fb2 100644 --- a/src/evaluator/parser/index.ts +++ b/src/evaluator/parser/index.ts @@ -54,6 +54,7 @@ export default function parser(log: ILogger, conditions: ISplitCondition[], stor } predicates.push(conditionFactory( + log, andCombiner(expressions, log), Treatments.parse(partitions), label, From 765ce1c21ec8c5a0abc29699af14d72824efef3f Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 10 Mar 2021 18:28:25 -0300 Subject: [PATCH 22/58] polishing --- src/evaluator/Engine.ts | 2 +- .../__tests__/evaluate-feature.spec.ts | 20 ++++---- .../__tests__/evaluate-features.spec.ts | 4 +- src/evaluator/combiners/__tests__/and.spec.ts | 4 +- .../combiners/__tests__/ifelseif.spec.ts | 6 +-- src/evaluator/combiners/and.ts | 2 +- src/evaluator/combiners/ifelseif.ts | 2 +- src/evaluator/index.ts | 22 ++++----- src/evaluator/matchers/dependency.ts | 2 +- src/evaluator/parser/index.ts | 6 +-- src/evaluator/types.ts | 2 +- src/evaluator/value/index.ts | 8 ++-- src/evaluator/value/sanitize.ts | 2 +- src/integrations/__tests__/browser.spec.ts | 2 +- src/integrations/ga/GaToSplit.ts | 5 +- src/integrations/ga/SplitToGa.ts | 7 +-- src/integrations/ga/SplitToGaPlugin.ts | 2 +- .../ga/__tests__/GaToSplit.spec.ts | 14 +++--- .../ga/__tests__/SplitToGa.spec.ts | 48 +++++++++---------- .../__tests__/sdkReadinessManager.spec.ts | 22 ++++----- src/readiness/sdkReadinessManager.ts | 4 +- src/sdkClient/client.ts | 4 +- src/sdkClient/clientInputValidation.ts | 2 +- src/sdkClient/sdkClient.ts | 2 +- src/sdkFactory/index.ts | 2 +- src/storages/types.ts | 2 +- .../splitsParser/splitsParserFromFile.ts | 8 ++-- .../offline/syncTasks/fromObjectSyncTask.ts | 2 +- .../__tests__/splitChangesUpdater.spec.ts | 2 +- .../polling/syncTasks/mySegmentsSyncTask.ts | 6 +-- .../polling/syncTasks/segmentsSyncTask.ts | 8 ++-- src/sync/polling/syncTasks/splitsSyncTask.ts | 6 +-- .../SSEHandler/__tests__/index.spec.ts | 12 ++--- src/sync/streaming/SSEHandler/index.ts | 3 +- src/sync/streaming/pushManager.ts | 2 +- src/sync/streaming/pushManagerCS.ts | 2 +- src/sync/streaming/pushManagerSS.ts | 2 +- src/sync/submitters/eventsSyncTask.ts | 4 +- .../submitters/impressionCountsSyncTask.ts | 4 +- src/sync/submitters/impressionsSyncTask.ts | 4 +- src/sync/submitters/metricsSyncTask.ts | 8 ++-- src/sync/submitters/submitterSyncTask.ts | 4 +- src/sync/syncManagerOnline.ts | 6 +-- src/sync/syncTask.ts | 2 +- src/utils/timeTracker/__tests__/index.spec.ts | 16 +++---- src/utils/timeTracker/index.ts | 22 ++++----- 46 files changed, 162 insertions(+), 159 deletions(-) diff --git a/src/evaluator/Engine.ts b/src/evaluator/Engine.ts index b9364b24..d7466caa 100644 --- a/src/evaluator/Engine.ts +++ b/src/evaluator/Engine.ts @@ -27,7 +27,7 @@ export default class Engine { } } - static parse(splitFlatStructure: ISplit, storage: IStorageSync | IStorageAsync, log: ILogger) { + static parse(log: ILogger, splitFlatStructure: ISplit, storage: IStorageSync | IStorageAsync) { const conditions = splitFlatStructure.conditions; const evaluator = parser(log, conditions, storage); diff --git a/src/evaluator/__tests__/evaluate-feature.spec.ts b/src/evaluator/__tests__/evaluate-feature.spec.ts index fdfdd94e..77af0c9d 100644 --- a/src/evaluator/__tests__/evaluate-feature.spec.ts +++ b/src/evaluator/__tests__/evaluate-feature.spec.ts @@ -32,11 +32,11 @@ test('EVALUATOR / should return label exception, treatment control and config nu config: null }; const evaluationPromise = evaluateFeature( + loggerMock, 'fake-key', 'throw_exception', null, mockStorage, - loggerMock ); // This validation is async because the only exception possible when retrieving a Split would happen with Async storages. @@ -56,88 +56,88 @@ test('EVALUATOR / should return right label, treatment and config if storage ret }; const evaluationWithConfig = evaluateFeature( + loggerMock, 'fake-key', 'config', null, mockStorage, - loggerMock ); expect(evaluationWithConfig).toEqual(expectedOutput); // If the split is retrieved successfully we should get the right evaluation result, label and config. const evaluationNotFound = evaluateFeature( + loggerMock, 'fake-key', 'not_existent_split', null, mockStorage, - loggerMock ); expect(evaluationNotFound).toEqual(expectedOutputControl); // If the split is not retrieved successfully because it does not exist, we should get the right evaluation result, label and config. const evaluation = evaluateFeature( + loggerMock, 'fake-key', 'regular', null, mockStorage, - loggerMock ); expect(evaluation).toEqual({ ...expectedOutput, config: null }); // If the split is retrieved successfully we should get the right evaluation result, label and config. If Split has no config it should have config equal null. const evaluationKilled = evaluateFeature( + loggerMock, 'fake-key', 'killed', null, mockStorage, - loggerMock ); expect(evaluationKilled).toEqual({ ...expectedOutput, treatment: 'off', config: null, label: LabelsConstants.SPLIT_KILLED }); // If the split is retrieved but is killed, we should get the right evaluation result, label and config. const evaluationArchived = evaluateFeature( + loggerMock, 'fake-key', 'archived', null, mockStorage, - loggerMock ); expect(evaluationArchived).toEqual({ ...expectedOutput, treatment: 'control', label: LabelsConstants.SPLIT_ARCHIVED, config: null }); // If the split is retrieved but is archived, we should get the right evaluation result, label and config. const evaluationtrafficAlocation1 = evaluateFeature( + loggerMock, 'fake-key', 'trafficAlocation1', null, mockStorage, - loggerMock ); expect(evaluationtrafficAlocation1).toEqual({ ...expectedOutput, label: LabelsConstants.NOT_IN_SPLIT, config: null, treatment: 'off' }); // If the split is retrieved but is not in split (out of Traffic Allocation), we should get the right evaluation result, label and config. const evaluationKilledWithConfig = evaluateFeature( + loggerMock, 'fake-key', 'killedWithConfig', null, mockStorage, - loggerMock ); expect(evaluationKilledWithConfig).toEqual({ ...expectedOutput, treatment: 'off', label: LabelsConstants.SPLIT_KILLED }); // If the split is retrieved but is killed, we should get the right evaluation result, label and config. const evaluationArchivedWithConfig = evaluateFeature( + loggerMock, 'fake-key', 'archivedWithConfig', null, mockStorage, - loggerMock ); expect(evaluationArchivedWithConfig).toEqual({ ...expectedOutput, treatment: 'control', label: LabelsConstants.SPLIT_ARCHIVED, config: null }); // If the split is retrieved but is archived, we should get the right evaluation result, label and config. const evaluationtrafficAlocation1WithConfig = evaluateFeature( + loggerMock, 'fake-key', 'trafficAlocation1WithConfig', null, mockStorage, - loggerMock ); expect(evaluationtrafficAlocation1WithConfig).toEqual({ ...expectedOutput, label: LabelsConstants.NOT_IN_SPLIT, treatment: 'off' }); // If the split is retrieved but is not in split (out of Traffic Allocation), we should get the right evaluation result, label and config. diff --git a/src/evaluator/__tests__/evaluate-features.spec.ts b/src/evaluator/__tests__/evaluate-features.spec.ts index 2b3cddb6..7f836d1b 100644 --- a/src/evaluator/__tests__/evaluate-features.spec.ts +++ b/src/evaluator/__tests__/evaluate-features.spec.ts @@ -44,11 +44,11 @@ test('EVALUATOR - Multiple evaluations at once / should return label exception, // This validation is async because the only exception possible when retrieving a Split would happen with Async storages. const evaluation = await evaluateFeatures( + loggerMock, 'fake-key', ['throw_exception'], null, mockStorage, - loggerMock ); expect(evaluation).toEqual(expectedOutput); // If there was an error on the `getSplits` we should get the results for exception. @@ -68,11 +68,11 @@ test('EVALUATOR - Multiple evaluations at once / should return right labels, tre }; const multipleEvaluationAtOnce = await evaluateFeatures( + loggerMock, 'fake-key', ['config', 'not_existent_split', 'regular', 'killed', 'archived', 'trafficAlocation1', 'killedWithConfig', 'archivedWithConfig', 'trafficAlocation1WithConfig'], null, mockStorage, - loggerMock ); // assert evaluationWithConfig expect(multipleEvaluationAtOnce['config']).toEqual(expectedOutput['config']); // If the split is retrieved successfully we should get the right evaluation result, label and config. diff --git a/src/evaluator/combiners/__tests__/and.spec.ts b/src/evaluator/combiners/__tests__/and.spec.ts index 3f71c016..1990546e 100644 --- a/src/evaluator/combiners/__tests__/and.spec.ts +++ b/src/evaluator/combiners/__tests__/and.spec.ts @@ -3,14 +3,14 @@ import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; test('COMBINER AND / should always return true', async function () { - let AND = andCombiner([() => true, () => true, () => true], loggerMock); + let AND = andCombiner(loggerMock, [() => true, () => true, () => true]); expect(await AND('always true')).toBe(true); // should always return true }); test('COMBINER AND / should always return false', async function () { - let AND = andCombiner([() => true, () => true, () => false], loggerMock); + let AND = andCombiner(loggerMock, [() => true, () => true, () => false]); expect(await AND('always false')).toBe(false); // should always return false }); diff --git a/src/evaluator/combiners/__tests__/ifelseif.spec.ts b/src/evaluator/combiners/__tests__/ifelseif.spec.ts index dba32cfd..eb874ebc 100644 --- a/src/evaluator/combiners/__tests__/ifelseif.spec.ts +++ b/src/evaluator/combiners/__tests__/ifelseif.spec.ts @@ -17,7 +17,7 @@ test('IF ELSE IF COMBINER / should correctly propagate context parameters and pr } let predicates = [evaluator]; - let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, loggerMock); + let ifElseIfEvaluator = ifElseIfCombinerFactory(loggerMock, predicates); expect(await ifElseIfEvaluator(inputKey, inputSeed, inputAttributes) === evaluationResult).toBe(true); console.log(`evaluator should return ${evaluationResult}`); @@ -36,7 +36,7 @@ test('IF ELSE IF COMBINER / should stop evaluating when one matcher return a tre } ]; - let ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, loggerMock); + let ifElseIfEvaluator = ifElseIfCombinerFactory(loggerMock, predicates); expect(await ifElseIfEvaluator()).toBe('exclude'); // exclude treatment found }); @@ -54,7 +54,7 @@ test('IF ELSE IF COMBINER / should return undefined if there is none matching ru } ]; - const ifElseIfEvaluator = ifElseIfCombinerFactory(predicates, loggerMock); + const ifElseIfEvaluator = ifElseIfCombinerFactory(loggerMock, predicates); expect(await ifElseIfEvaluator() === undefined).toBe(true); }); diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index 5fa02e11..7f9b43c7 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -6,7 +6,7 @@ import thenable from '../../utils/promise/thenable'; import { MaybeThenable } from '../../dtos/types'; import { IMatcher } from '../types'; -export default function andCombinerContext(matchers: IMatcher[], log: ILogger) { +export default function andCombinerContext(log: ILogger, matchers: IMatcher[]) { function andResults(results: boolean[]): boolean { // Array.prototype.every is supported by target environments diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index 2cdc7874..23f45183 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -8,7 +8,7 @@ import { CONTROL } from '../../utils/constants'; import { SplitIO } from '../../types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; -export default function ifElseIfCombinerContext(predicates: IEvaluator[], log: ILogger): IEvaluator { +export default function ifElseIfCombinerContext(log: ILogger, predicates: IEvaluator[]): IEvaluator { function unexpectedInputHandler() { log.error('Invalid Split provided, no valid conditions found'); diff --git a/src/evaluator/index.ts b/src/evaluator/index.ts index 619b9e97..8dd5aa14 100644 --- a/src/evaluator/index.ts +++ b/src/evaluator/index.ts @@ -16,11 +16,11 @@ const treatmentException = { }; export function evaluateFeature( + log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync, - log: ILogger ): MaybeThenable { let stringifiedSplit; @@ -35,29 +35,29 @@ export function evaluateFeature( if (thenable(stringifiedSplit)) { return stringifiedSplit.then((result) => getEvaluation( + log, result, key, attributes, storage, - log )); } return getEvaluation( + log, stringifiedSplit, key, attributes, storage, - log ); } export function evaluateFeatures( + log: ILogger, key: SplitIO.SplitKey, splitNames: string[], attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync, - log: ILogger ): MaybeThenable> { let stringifiedSplits; const evaluations: Record = {}; @@ -75,16 +75,16 @@ export function evaluateFeatures( } return (thenable(stringifiedSplits)) ? - stringifiedSplits.then(splits => getEvaluations(splitNames, splits, key, attributes, storage, log)) : - getEvaluations(splitNames, stringifiedSplits, key, attributes, storage, log); + stringifiedSplits.then(splits => getEvaluations(log, splitNames, splits, key, attributes, storage)) : + getEvaluations(log, splitNames, stringifiedSplits, key, attributes, storage); } function getEvaluation( + log: ILogger, stringifiedSplit: string | null, key: SplitIO.SplitKey, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync, - log: ILogger ): MaybeThenable { let evaluation: MaybeThenable = { treatment: CONTROL, @@ -94,7 +94,7 @@ function getEvaluation( if (stringifiedSplit) { const splitJSON: ISplit = JSON.parse(stringifiedSplit); - const split = Engine.parse(splitJSON, storage, log); + const split = Engine.parse(log, splitJSON, storage); evaluation = split.getTreatment(key, attributes, evaluateFeature); // If the storage is async, evaluation and changeNumber will return a thenable @@ -115,22 +115,22 @@ function getEvaluation( } function getEvaluations( + log: ILogger, splitNames: string[], splits: Record, key: SplitIO.SplitKey, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync, - log: ILogger ): MaybeThenable> { const result: Record = {}; const thenables: Promise[] = []; splitNames.forEach(splitName => { const evaluation = getEvaluation( + log, splits[splitName], key, attributes, - storage, - log + storage ); if (thenable(evaluation)) { thenables.push(evaluation.then(res => { diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index e0778649..aadab6bc 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -22,7 +22,7 @@ export default function dependencyMatcherContext(log: ILogger, { split, treatmen return function dependencyMatcher({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator): MaybeThenable { log.debug(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? `\n attributes: ${JSON.stringify(attributes)}` : ''}`); - const evaluation = splitEvaluator(key, split, attributes, storage, log); + const evaluation = splitEvaluator(log, key, split, attributes, storage); if (thenable(evaluation)) { return evaluation.then(ev => checkTreatment(ev, treatments, split)); diff --git a/src/evaluator/parser/index.ts b/src/evaluator/parser/index.ts index d2187fb2..4fdc6f0f 100644 --- a/src/evaluator/parser/index.ts +++ b/src/evaluator/parser/index.ts @@ -32,7 +32,7 @@ export default function parser(log: ILogger, conditions: ISplitCondition[], stor // Evaluator function. return (key: string, attributes: SplitIO.Attributes, splitEvaluator: ISplitEvaluator) => { - const value = sanitizeValue(key, matcherDto, attributes, log); + const value = sanitizeValue(log, key, matcherDto, attributes); const result = value !== undefined && matcher ? matcher(value, splitEvaluator) : false; if (thenable(result)) { @@ -55,7 +55,7 @@ export default function parser(log: ILogger, conditions: ISplitCondition[], stor predicates.push(conditionFactory( log, - andCombiner(expressions, log), + andCombiner(log, expressions), Treatments.parse(partitions), label, conditionType @@ -63,5 +63,5 @@ export default function parser(log: ILogger, conditions: ISplitCondition[], stor } // Instanciate evaluator given the set of conditions using if else if logic - return ifElseIfCombiner(predicates, log); + return ifElseIfCombiner(log, predicates); } diff --git a/src/evaluator/types.ts b/src/evaluator/types.ts index 3befebeb..ccab4db8 100644 --- a/src/evaluator/types.ts +++ b/src/evaluator/types.ts @@ -27,7 +27,7 @@ export interface IEvaluation { export type IEvaluationResult = IEvaluation & { treatment: string } -export type ISplitEvaluator = (key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes, storage: IStorageSync | IStorageAsync, log: ILogger) => MaybeThenable +export type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes, storage: IStorageSync | IStorageAsync) => MaybeThenable export type IEvaluator = (key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index 91d3a18a..55442286 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -5,7 +5,7 @@ import { IMatcherDto } from '../types'; import { ILogger } from '../../logger/types'; import sanitizeValue from './sanitize'; -function parseValue(key: string, attributeName: string | null, attributes: SplitIO.Attributes, log: ILogger) { +function parseValue(log: ILogger, key: string, attributeName: string | null, attributes: SplitIO.Attributes) { let value = undefined; if (attributeName) { if (attributes) { @@ -24,10 +24,10 @@ function parseValue(key: string, attributeName: string | null, attributes: Split /** * Defines value to be matched (key / attribute). */ -export default function value(key: string, matcherDto: IMatcherDto, attributes: SplitIO.Attributes, log: ILogger) { +export default function value(log: ILogger, key: string, matcherDto: IMatcherDto, attributes: SplitIO.Attributes) { const attributeName = matcherDto.attribute; - const valueToMatch = parseValue(key, attributeName, attributes, log); - const sanitizedValue = sanitizeValue(matcherDto.type, valueToMatch, matcherDto.dataType, attributes, log); + const valueToMatch = parseValue(log, key, attributeName, attributes); + const sanitizedValue = sanitizeValue(log, matcherDto.type, valueToMatch, matcherDto.dataType, attributes); if (sanitizedValue !== undefined) { return sanitizedValue; diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index ff1a98d5..d7c90102 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -70,7 +70,7 @@ function getProcessingFunction(matcherTypeID: number, dataType: string) { /** * Sanitize matcher value */ -export default function sanitize(matcherTypeID: number, value: string | number | boolean | Array | undefined, dataType: string, attributes: SplitIO.Attributes, log: ILogger) { +export default function sanitize(log: ILogger, matcherTypeID: number, value: string | number | boolean | Array | undefined, dataType: string, attributes: SplitIO.Attributes) { const processor = getProcessingFunction(matcherTypeID, dataType); let sanitizedValue: string | number | boolean | Array | IDependencyMatcherValue | undefined; diff --git a/src/integrations/__tests__/browser.spec.ts b/src/integrations/__tests__/browser.spec.ts index 9121a4c0..e4237f91 100644 --- a/src/integrations/__tests__/browser.spec.ts +++ b/src/integrations/__tests__/browser.spec.ts @@ -81,7 +81,7 @@ describe('IntegrationsManagerFactory for browser', () => { }]; const instance = browserIMF(integrations, fakeParams as any); - expect((SplitToGaMock as unknown as jest.Mock).mock.calls).toEqual([[integrations[0], fakeParams.settings.log]]); // Invokes SplitToGa integration module with options + expect((SplitToGaMock as unknown as jest.Mock).mock.calls).toEqual([[fakeParams.settings.log, integrations[0]]]); // Invokes SplitToGa integration module with options const fakeImpression = 'fake'; // @ts-expect-error instance.handleImpression(fakeImpression); diff --git a/src/integrations/ga/GaToSplit.ts b/src/integrations/ga/GaToSplit.ts index 0346044d..60bc6f81 100644 --- a/src/integrations/ga/GaToSplit.ts +++ b/src/integrations/ga/GaToSplit.ts @@ -154,10 +154,11 @@ const INVALID_SUBSTRING_REGEX = /[^-_.:a-zA-Z0-9]+/g; /** * Fixes the passed string value to comply with EventTypeId format, by removing invalid characters and truncating if necessary. * + * @param {object} log factory logger * @param {string} eventTypeId string value to fix. * @returns {string} Fixed version of `eventTypeId`. */ -export function fixEventTypeId(eventTypeId: any, log: ILogger) { +export function fixEventTypeId(log: ILogger, eventTypeId: any) { // return the input eventTypeId if it cannot be fixed if (!isString(eventTypeId) || eventTypeId.length === 0) { return eventTypeId; @@ -258,7 +259,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par // Add prefix. Nothing is appended if the prefix is falsy, e.g. undefined or ''. if (opts.prefix) eventData.eventTypeId = `${opts.prefix}.${eventData.eventTypeId}`; - eventData.eventTypeId = fixEventTypeId(eventData.eventTypeId, log); + eventData.eventTypeId = fixEventTypeId(log, eventData.eventTypeId); if (!validateEventData(log, eventData)) return; diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index 7e01dfdf..acab8642 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -56,10 +56,11 @@ export default class SplitToGa implements IIntegration { * Other validations (e.g., an `event` hitType must have a `eventCategory` and `eventAction`) are handled * and logged (as warnings or errors depending the case) by GA debugger, but the hit is sent anyway. * + * @param {object} log factory logger * @param {UniversalAnalytics.FieldsObject} fieldsObject object to validate. * @returns {boolean} Whether the data instance is a valid FieldsObject or not. */ - static validateFieldsObject(fieldsObject: any, log: ILogger): fieldsObject is UniversalAnalytics.FieldsObject { + static validateFieldsObject(log: ILogger, fieldsObject: any): fieldsObject is UniversalAnalytics.FieldsObject { if (fieldsObject && fieldsObject.hitType) return true; log.warn('your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.'); @@ -70,7 +71,7 @@ export default class SplitToGa implements IIntegration { * constructor description * @param {object} options options passed at the SDK integrations settings (isomorphic SDK) or the SplitToGoogleAnalytics plugin (pluggable browser SDK) */ - constructor(options: SplitToGoogleAnalyticsOptions, log: ILogger) { + constructor(log: ILogger, options: SplitToGoogleAnalyticsOptions) { this.trackerNames = SplitToGa.defaultTrackerNames; this.log = log; @@ -111,7 +112,7 @@ export default class SplitToGa implements IIntegration { if (this.mapper) { fieldsObject = this.mapper(data, fieldsObject); // don't send the hit if it is falsy or invalid - if (!fieldsObject || !SplitToGa.validateFieldsObject(fieldsObject, this.log)) return; + if (!fieldsObject || !SplitToGa.validateFieldsObject(this.log, fieldsObject)) return; } } catch (err) { this.log.warn(`SplitToGa queue method threw: ${err}. No hit was sent.`); diff --git a/src/integrations/ga/SplitToGaPlugin.ts b/src/integrations/ga/SplitToGaPlugin.ts index 0556143c..9001c180 100644 --- a/src/integrations/ga/SplitToGaPlugin.ts +++ b/src/integrations/ga/SplitToGaPlugin.ts @@ -6,6 +6,6 @@ export default function SplitToGaPlugin(options: SplitToGoogleAnalyticsOptions = // SplitToGa integration factory return (params: IIntegrationFactoryParams) => { - return new SplitToGa(options, params.settings.log); + return new SplitToGa(params.settings.log, options); }; } diff --git a/src/integrations/ga/__tests__/GaToSplit.spec.ts b/src/integrations/ga/__tests__/GaToSplit.spec.ts index df416639..d9005ead 100644 --- a/src/integrations/ga/__tests__/GaToSplit.spec.ts +++ b/src/integrations/ga/__tests__/GaToSplit.spec.ts @@ -81,13 +81,13 @@ test('validateEventData', () => { }); test('fixEventTypeId', () => { - expect(fixEventTypeId(undefined, loggerMock)).toBe(undefined); - expect(fixEventTypeId(111, loggerMock)).toBe(111); - expect(fixEventTypeId('', loggerMock)).toBe(''); - expect(fixEventTypeId('()', loggerMock)).toBe(''); - expect(fixEventTypeId('()+_', loggerMock)).toBe(''); - expect(fixEventTypeId(' some event ', loggerMock)).toBe('some_event_'); - expect(fixEventTypeId(' -*- some -.%^ event =+ ', loggerMock)).toBe('some_-._event_'); + expect(fixEventTypeId(loggerMock, undefined)).toBe(undefined); + expect(fixEventTypeId(loggerMock, 111)).toBe(111); + expect(fixEventTypeId(loggerMock, '')).toBe(''); + expect(fixEventTypeId(loggerMock, '()')).toBe(''); + expect(fixEventTypeId(loggerMock, '()+_')).toBe(''); + expect(fixEventTypeId(loggerMock, ' some event ')).toBe('some_event_'); + expect(fixEventTypeId(loggerMock, ' -*- some -.%^ event =+ ')).toBe('some_-._event_'); }); test('defaultMapper', () => { diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index 1766bd4e..cf6100c6 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -58,17 +58,17 @@ const defaultEventFieldsObject = { describe('SplitToGa', () => { test('SplitToGa.validateFieldsObject', () => { - expect(SplitToGa.validateFieldsObject(undefined, loggerMock)).toBe(false); - expect(SplitToGa.validateFieldsObject(null, loggerMock)).toBe(false); - expect(SplitToGa.validateFieldsObject(123, loggerMock)).toBe(false); - expect(SplitToGa.validateFieldsObject(true, loggerMock)).toBe(false); - expect(SplitToGa.validateFieldsObject('something', loggerMock)).toBe(false); - expect(SplitToGa.validateFieldsObject(/asd/ig, loggerMock)).toBe(false); - expect(SplitToGa.validateFieldsObject(function () { }, loggerMock)).toBe(false); - - expect(SplitToGa.validateFieldsObject({}, loggerMock)).toBe(false); // An empty object is an invalid FieldsObject instance - expect(SplitToGa.validateFieldsObject({ hitType: 10 }, loggerMock)).toBe(true); // A fields object instance must have a HitType - expect(SplitToGa.validateFieldsObject({ hitType: 'event', ignoredProp: 'ignoredProp' }, loggerMock)).toBe(true); // A fields object instance must have a HitType + expect(SplitToGa.validateFieldsObject(loggerMock, undefined)).toBe(false); + expect(SplitToGa.validateFieldsObject(loggerMock, null)).toBe(false); + expect(SplitToGa.validateFieldsObject(loggerMock, 123)).toBe(false); + expect(SplitToGa.validateFieldsObject(loggerMock, true)).toBe(false); + expect(SplitToGa.validateFieldsObject(loggerMock, 'something')).toBe(false); + expect(SplitToGa.validateFieldsObject(loggerMock, /asd/ig)).toBe(false); + expect(SplitToGa.validateFieldsObject(loggerMock, function () { })).toBe(false); + + expect(SplitToGa.validateFieldsObject(loggerMock, {})).toBe(false); // An empty object is an invalid FieldsObject instance + expect(SplitToGa.validateFieldsObject(loggerMock, { hitType: 10 })).toBe(true); // A fields object instance must have a HitType + expect(SplitToGa.validateFieldsObject(loggerMock, { hitType: 'event', ignoredProp: 'ignoredProp' })).toBe(true); // A fields object instance must have a HitType }); test('SplitToGa.defaultMapper', () => { @@ -84,14 +84,14 @@ describe('SplitToGa', () => { const { ga } = gaMock(); expect(SplitToGa.getGa()).toBe(ga); // should return ga command queue if it exists - let integration = new SplitToGa({}, loggerMock); + let integration = new SplitToGa(loggerMock, {}); expect(typeof integration).toBe('object'); expect(loggerMock.warn.mock.calls.length).toBe(0); gaRemove(); expect(SplitToGa.getGa()).toBe(undefined); // should return undefined if ga command queue does not exist - integration = new SplitToGa({}, loggerMock); + integration = new SplitToGa(loggerMock, {}); expect(typeof integration).toBe('object'); // SplitToGa instances should be created even if ga command queue does not exist // @ts-expect-error integration.queue('fake-data'); @@ -107,7 +107,7 @@ describe('SplitToGa', () => { const { ga } = gaMock(); /** Default behaviour **/ - const instance = new SplitToGa({}, loggerMock) as SplitToGa; + const instance = new SplitToGa(loggerMock, {}) as SplitToGa; instance.queue(fakeImpression); // should queue `ga send` with the default mapped FieldsObject for impressions, appended with `splitHit` field expect(ga.mock.calls[ga.mock.calls.length - 1]).toEqual(['send', { ...defaultImpressionFieldsObject, splitHit: true }]); @@ -131,11 +131,11 @@ describe('SplitToGa', () => { } as UniversalAnalytics.FieldsObject; } const trackerNames = ['', 'namedTracker']; - const instance2 = new SplitToGa({ + const instance2 = new SplitToGa(loggerMock, { filter: customFilter, mapper: customMapper, trackerNames, - }, loggerMock) as SplitToGa; + }) as SplitToGa; ga.mockClear(); instance2.queue(fakeImpression); expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` if a Split data (impression or event) is filtered @@ -152,9 +152,9 @@ describe('SplitToGa', () => { function customMapper2(data: SplitIO.IntegrationData, defaultFieldsObject: UniversalAnalytics.FieldsObject) { return defaultFieldsObject; } - const instance3 = new SplitToGa({ + const instance3 = new SplitToGa(loggerMock, { mapper: customMapper2, - }, loggerMock) as SplitToGa; + }) as SplitToGa; ga.mockClear(); instance3.queue(fakeImpression); // should queue `ga send` with the custom FieldsObject from customMapper2, appended with `splitHit` field @@ -166,25 +166,25 @@ describe('SplitToGa', () => { function customMapper3() { throw 'some error'; } - const instance4 = new SplitToGa({ // @ts-expect-error + const instance4 = new SplitToGa(loggerMock, { // @ts-expect-error mapper: customMapper3, - }, loggerMock) as SplitToGa; + }) as SplitToGa; ga.mockClear(); instance4.queue(fakeImpression); expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` if a custom mapper throw an exception // `impressions` flags - const instance5 = new SplitToGa({ + const instance5 = new SplitToGa(loggerMock, { impressions: false, - }, loggerMock) as SplitToGa; + }) as SplitToGa; ga.mockClear(); instance5.queue(fakeImpression); expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` for an impression if `impressions` flag is false // `impressions` flags - const instance6 = new SplitToGa({ + const instance6 = new SplitToGa(loggerMock, { events: false, - }, loggerMock) as SplitToGa; + }) as SplitToGa; ga.mockClear(); instance6.queue(fakeEvent); expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` for a event if `events` flag is false diff --git a/src/readiness/__tests__/sdkReadinessManager.spec.ts b/src/readiness/__tests__/sdkReadinessManager.spec.ts index b00e5144..d148b1fa 100644 --- a/src/readiness/__tests__/sdkReadinessManager.spec.ts +++ b/src/readiness/__tests__/sdkReadinessManager.spec.ts @@ -41,7 +41,7 @@ describe('SDK Readiness Manager - Event emitter', () => { test('Providing the gate object to get the SDK status interface that manages events', () => { expect(typeof sdkReadinessManagerFactory).toBe('function'); // The module exposes a function. - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); expect(typeof sdkReadinessManager).toBe('object'); // The function result contains the readiness manager and a sdkStatus object. const gateMock = sdkReadinessManager.readinessManager.gate; const sdkStatus = sdkReadinessManager.sdkStatus; @@ -77,7 +77,7 @@ describe('SDK Readiness Manager - Event emitter', () => { }); test('The event callbacks should work as expected - SDK_READY_FROM_CACHE', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); const gateMock = sdkReadinessManager.readinessManager.gate; const readyFromCacheEventCB = gateMock.once.mock.calls[2][1]; @@ -87,7 +87,7 @@ describe('SDK Readiness Manager - Event emitter', () => { }); test('The event callbacks should work as expected - SDK_READY emits with no callbacks', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); // Get the callbacks const addListenerCB = sdkReadinessManager.readinessManager.gate.on.mock.calls[1][1]; @@ -113,7 +113,7 @@ describe('SDK Readiness Manager - Event emitter', () => { }); test('The event callbacks should work as expected - SDK_READY emits with callbacks', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); // Get the callbacks const addListenerCB = sdkReadinessManager.readinessManager.gate.on.mock.calls[1][1]; @@ -131,7 +131,7 @@ describe('SDK Readiness Manager - Event emitter', () => { }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); const gateMock = sdkReadinessManager.readinessManager.gate; // Get the callbacks @@ -151,7 +151,7 @@ describe('SDK Readiness Manager - Event emitter', () => { }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); const gateMock = sdkReadinessManager.readinessManager.gate; // Get the callbacks @@ -173,7 +173,7 @@ describe('SDK Readiness Manager - Event emitter', () => { test('The event callbacks should work as expected - SDK_READY emits with expected internal callbacks', () => { // the sdkReadinessManager expects more than one SDK_READY callback to not log the "No listeners" warning - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock, undefined /* default readyTimeout */, 1 /* internalReadyCbCount */); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock, undefined /* default readyTimeout */, 1 /* internalReadyCbCount */); const gateMock = sdkReadinessManager.readinessManager.gate; // Get the callbacks @@ -197,7 +197,7 @@ describe('SDK Readiness Manager - Event emitter', () => { describe('SDK Readiness Manager - Ready promise', () => { test('.ready() promise behaviour for clients', async (done) => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); const ready = sdkReadinessManager.sdkStatus.ready(); expect(ready instanceof Promise).toBe(true); // It should return a promise. @@ -226,7 +226,7 @@ describe('SDK Readiness Manager - Ready promise', () => { // control assertion. stubs already reset. expect(testPassedCount).toBe(2); - const sdkReadinessManagerForTimedout = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManagerForTimedout = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); const readyForTimeout = sdkReadinessManagerForTimedout.sdkStatus.ready(); @@ -266,7 +266,7 @@ describe('SDK Readiness Manager - Ready promise', () => { }); test('Full blown ready promise count as a callback and resolves on SDK_READY', (done) => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); const readyPromise = sdkReadinessManager.sdkStatus.ready(); // Get the callback @@ -288,7 +288,7 @@ describe('SDK Readiness Manager - Ready promise', () => { }); test('.ready() rejected promises have a default onRejected handler that just logs the error', (done) => { - const sdkReadinessManager = sdkReadinessManagerFactory(EventEmitterMock, loggerMock); + const sdkReadinessManager = sdkReadinessManagerFactory(loggerMock, EventEmitterMock); let readyForTimeout = sdkReadinessManager.sdkStatus.ready(); emitTimeoutEvent(sdkReadinessManager.readinessManager); // make the SDK "timed out" diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index b43f4d3e..486c4822 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -21,8 +21,8 @@ const REMOVE_LISTENER_EVENT = 'removeListener'; * @param readinessManager optional readinessManager to use. only used internally for `shared` method */ export default function sdkReadinessManagerFactory( - EventEmitter: new () => IEventEmitter, log: ILogger, + EventEmitter: new () => IEventEmitter, readyTimeout = 0, internalReadyCbCount = 0, readinessManager = readinessManagerFactory(EventEmitter, readyTimeout)): ISdkReadinessManager { @@ -74,7 +74,7 @@ export default function sdkReadinessManagerFactory( readinessManager, shared(readyTimeout = 0, internalReadyCbCount = 0) { - return sdkReadinessManagerFactory(EventEmitter, log, readyTimeout, internalReadyCbCount, readinessManager.shared(readyTimeout)); + return sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, internalReadyCbCount, readinessManager.shared(readyTimeout)); }, sdkStatus: objectAssign( diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index b1b7e194..e34d682e 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -27,7 +27,7 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl return treatment; }; - const evaluation = evaluateFeature(key, splitName, attributes, storage, log); + const evaluation = evaluateFeature(log, key, splitName, attributes, storage); return thenable(evaluation) ? evaluation.then((res) => wrapUp(res)) : wrapUp(evaluation); } @@ -47,7 +47,7 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl return treatments; }; - const evaluations = evaluateFeatures(key, splitNames, attributes, storage, log); + const evaluations = evaluateFeatures(log, key, splitNames, attributes, storage); return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations); } diff --git a/src/sdkClient/clientInputValidation.ts b/src/sdkClient/clientInputValidation.ts index e52b311d..93e7fca8 100644 --- a/src/sdkClient/clientInputValidation.ts +++ b/src/sdkClient/clientInputValidation.ts @@ -22,7 +22,7 @@ import { ILogger } from '../logger/types'; * Decorator that validates the input before actually executing the client methods. * We should "guard" the client here, while not polluting the "real" implementation of those methods. */ -export default function clientInputValidationDecorator(client: TClient, readinessManager: IReadinessManager, isStorageSync = false, log: ILogger): TClient { +export default function clientInputValidationDecorator(log: ILogger, client: TClient, readinessManager: IReadinessManager, isStorageSync = false): TClient { /** * Avoid repeating this validations code diff --git a/src/sdkClient/sdkClient.ts b/src/sdkClient/sdkClient.ts index ddf5e790..dd325dcb 100644 --- a/src/sdkClient/sdkClient.ts +++ b/src/sdkClient/sdkClient.ts @@ -18,11 +18,11 @@ export function sdkClientFactory(params: ISdkClientFactoryParams): SplitIO.IClie // Client API (getTreatment* & track methods) clientInputValidationDecorator( + settings.log, clientFactory(params), sdkReadinessManager.readinessManager, // @TODO isStorageSync could be extracted from the storage itself (e.g. `storage.isSync`) to simplify interfaces settings.mode === CONSUMER_MODE ? false : true, - settings.log ), // Sdk destroy diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 2288e95b..301d47ac 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -30,7 +30,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. const metadata = buildMetadata(settings); // @TODO handle non-recoverable error, such as, `fetch` api not available, invalid API Key, etc. - const sdkReadinessManager = sdkReadinessManagerFactory(platform.EventEmitter, log, settings.startup.readyTimeout); + const sdkReadinessManager = sdkReadinessManagerFactory(log, platform.EventEmitter, settings.startup.readyTimeout); const storageFactoryParams = { eventsQueueSize: settings.scheduler.eventsQueueSize, diff --git a/src/storages/types.ts b/src/storages/types.ts index f9626ea6..c4b94ad2 100644 --- a/src/storages/types.ts +++ b/src/storages/types.ts @@ -237,6 +237,7 @@ export type IStorageAsync = IStorageBase< export type DataLoader = (storage: IStorageSync, matchingKey: string) => void export interface IStorageFactoryParams { + log: ILogger, eventsQueueSize: number, optimize: boolean /* whether create the `impressionCounts` cache (OPTIMIZED impression mode) or not (DEBUG impression mode) */, dataLoader?: DataLoader, @@ -248,5 +249,4 @@ export interface IStorageFactoryParams { // ATM, only used by InRedisStorage. @TODO pass a callback to simplify custom storages. readinessManager: IReadinessManager, metadata: IMetadata, - log: ILogger } diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index 6f06e553..a94eb997 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -40,7 +40,7 @@ function configFilesPath(configFilePath?: SplitIO.MockedFeaturesFilePath): Split } // Parse `.split` configuration file and return a map of "Split Objects" -function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILogger): false | Record { +function readSplitConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFilePath): false | Record { const SPLIT_POSITION = 0; const TREATMENT_POSITION = 1; let data; @@ -80,7 +80,7 @@ function readSplitConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILog } // Parse `.yml` or `.yaml` configuration files and return a map of "Split Objects" -function readYAMLConfigFile(filePath: SplitIO.MockedFeaturesFilePath, log: ILogger): false | Record { +function readYAMLConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFilePath): false | Record { let data = ''; let yamldoc = null; @@ -168,9 +168,9 @@ export default function splitsParserFromFile({ features, log }: { features?: Spl // If we have a filePath, it means the extension is correct, choose the parser. if (endsWith(filePath, '.split')) { log.warn('.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'); - mockData = readSplitConfigFile(filePath, log); + mockData = readSplitConfigFile(log, filePath); } else { - mockData = readYAMLConfigFile(filePath, log); + mockData = readYAMLConfigFile(log, filePath); } return mockData; diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index f6f14ebd..cb8738db 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -78,6 +78,7 @@ export default function fromObjectSyncTaskFactory( settings: ISettings ): ISyncTask<[], boolean> { return syncTaskFactory( + settings.log, fromObjectUpdaterFactory( splitsParser, storage, @@ -86,6 +87,5 @@ export default function fromObjectSyncTaskFactory( ), settings.scheduler.offlineRefreshRate, 'offlineUpdater', - settings.log ); } diff --git a/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts b/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts index 2717eeea..ef1e20aa 100644 --- a/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts +++ b/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts @@ -70,7 +70,7 @@ test('splitChangesUpdater / factory', (done) => { const readinessManager = readinessManagerFactory(EventEmitter); const splitsEmitSpy = jest.spyOn(readinessManager.splits, 'emit'); - const splitChangesUpdater = splitChangesUpdaterFactory(splitChangesFetcher, splitsCache, segmentsCache, readinessManager.splits, 1000, 1, loggerMock); + const splitChangesUpdater = splitChangesUpdaterFactory(loggerMock, splitChangesFetcher, splitsCache, segmentsCache, readinessManager.splits, 1000, 1); splitChangesUpdater().then((result) => { expect(setChangeNumber.mock.calls.length).toBe(1); diff --git a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts index 53347bfa..a47787c6 100644 --- a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts @@ -22,13 +22,13 @@ type IMySegmentsUpdater = (segmentList?: string[], noCache?: boolean) => Promise * - uses `segmentsEventEmitter` to emit events related to segments data updates */ function mySegmentsUpdaterFactory( + log: ILogger, mySegmentsFetcher: IMySegmentsFetcher, splitsCache: ISplitsCacheSync, mySegmentsCache: ISegmentsCacheSync, segmentsEventEmitter: ISegmentsEventEmitter, requestTimeoutBeforeReady: number, retriesOnFailureBeforeReady: number, - log: ILogger ): IMySegmentsUpdater { let readyOnAlreadyExistentState = true; @@ -105,17 +105,17 @@ export default function mySegmentsSyncTaskFactory( matchingKey: string ): ISegmentsSyncTask { return syncTaskFactory( + settings.log, mySegmentsUpdaterFactory( + settings.log, mySegmentsFetcherFactory(fetchMySegments, matchingKey), storage.splits, storage.segments, readiness.segments, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, - settings.log ), settings.scheduler.segmentsRefreshRate, 'mySegmentsUpdater', - settings.log ); } diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index b1d27c4c..b22c605f 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -23,10 +23,10 @@ type ISegmentChangesUpdater = (segmentNames?: string[], noCache?: boolean, fetch * - uses `segmentsEventEmitter` to emit events related to segments data updates */ function segmentChangesUpdaterFactory( + log: ILogger, segmentChangesFetcher: ISegmentChangesFetcher, segmentsCache: ISegmentsCacheSync, readiness: IReadinessManager, - log: ILogger ): ISegmentChangesUpdater { let readyOnAlreadyExistentState = true; @@ -114,14 +114,14 @@ export default function segmentsSyncTaskFactory( settings: ISettings, ): ISegmentsSyncTask { return syncTaskFactory( + settings.log, segmentChangesUpdaterFactory( + settings.log, segmentChangesFetcherFactory(fetchSegmentChanges), storage.segments, readiness, - settings.log ), settings.scheduler.segmentsRefreshRate, - 'segmentChangesUpdater', - settings.log + 'segmentChangesUpdater' ); } diff --git a/src/sync/polling/syncTasks/splitsSyncTask.ts b/src/sync/polling/syncTasks/splitsSyncTask.ts index 9edbd867..3bea3172 100644 --- a/src/sync/polling/syncTasks/splitsSyncTask.ts +++ b/src/sync/polling/syncTasks/splitsSyncTask.ts @@ -83,13 +83,13 @@ export function computeSplitsMutation(entries: ISplit[]): ISplitMutations { * Exported for testing purposes. */ export function splitChangesUpdaterFactory( + log: ILogger, splitChangesFetcher: ISplitChangesFetcher, splitsCache: ISplitsCacheSync, segmentsCache: ISegmentsCacheSync, splitsEventEmitter: ISplitsEventEmitter, requestTimeoutBeforeReady: number, retriesOnFailureBeforeReady: number, - log: ILogger ): ISplitChangesUpdater { let startingUp = true; @@ -185,17 +185,17 @@ export default function splitsSyncTaskFactory( settings: ISettings, ): ISplitsSyncTask { return syncTaskFactory( + settings.log, splitChangesUpdaterFactory( + settings.log, splitChangesFetcherFactory(fetchSplitChanges), storage.splits, storage.segments, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, - settings.log, ), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater', - settings.log ); } diff --git a/src/sync/streaming/SSEHandler/__tests__/index.spec.ts b/src/sync/streaming/SSEHandler/__tests__/index.spec.ts index a7b855af..52473d0d 100644 --- a/src/sync/streaming/SSEHandler/__tests__/index.spec.ts +++ b/src/sync/streaming/SSEHandler/__tests__/index.spec.ts @@ -29,7 +29,7 @@ const pushEmitter = { emit: jest.fn() }; test('`handleOpen` and `handlerMessage` for OCCUPANCY notifications (NotificationKeeper)', () => { pushEmitter.emit.mockClear(); - const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); + const sseHandler = SSEHandlerFactory(loggerMock, pushEmitter); // handleOpen @@ -72,7 +72,7 @@ test('`handleOpen` and `handlerMessage` for OCCUPANCY notifications (Notificatio test('`handlerMessage` for CONTROL notifications (NotificationKeeper)', () => { pushEmitter.emit.mockClear(); - const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); + const sseHandler = SSEHandlerFactory(loggerMock, pushEmitter); sseHandler.handleOpen(); // CONTROL messages @@ -100,7 +100,7 @@ test('`handlerMessage` for CONTROL notifications (NotificationKeeper)', () => { sseHandler.handleMessage(controlStreamingDisabledSec); // testing STREAMING_DISABLED with second region expect(pushEmitter.emit).toHaveBeenLastCalledWith(PUSH_NONRETRYABLE_ERROR); // must emit PUSH_NONRETRYABLE_ERROR if received a STREAMING_DISABLED control message - const sseHandler2 = SSEHandlerFactory(pushEmitter, loggerMock); + const sseHandler2 = SSEHandlerFactory(loggerMock, pushEmitter); sseHandler2.handleOpen(); sseHandler2.handleMessage(controlStreamingPausedSec); // testing STREAMING_PAUSED with second region @@ -112,7 +112,7 @@ test('`handlerMessage` for CONTROL notifications (NotificationKeeper)', () => { }); test('`handlerMessage` for update notifications (NotificationProcessor)', () => { - const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); + const sseHandler = SSEHandlerFactory(loggerMock, pushEmitter); sseHandler.handleOpen(); pushEmitter.emit.mockClear(); @@ -135,7 +135,7 @@ test('`handlerMessage` for update notifications (NotificationProcessor)', () => }); test('handleError', () => { - const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); + const sseHandler = SSEHandlerFactory(loggerMock, pushEmitter); sseHandler.handleOpen(); pushEmitter.emit.mockClear(); @@ -166,7 +166,7 @@ test('handleError', () => { }); test('handlerMessage: ignore invalid events', () => { - const sseHandler = SSEHandlerFactory(pushEmitter, loggerMock); + const sseHandler = SSEHandlerFactory(loggerMock, pushEmitter); sseHandler.handleOpen(); pushEmitter.emit.mockClear(); diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index 10cf36ec..5392d7ba 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -23,9 +23,10 @@ function isRetryableError(error: INotificationError) { /** * Factory for SSEHandler, which processes SSEClient messages and emits the corresponding push events. * + * @param log factory logger * @param pushEmitter emitter for events related to streaming support */ -export default function SSEHandlerFactory(pushEmitter: IPushEventEmitter, log: ILogger): ISseEventHandler { +export default function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventEmitter): ISseEventHandler { const notificationKeeper = notificationKeeperFactory(pushEmitter); diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index 7513f53a..d156f110 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -48,7 +48,7 @@ export default function pushManagerFactory( // init feedback loop const pushEmitter = new platform.EventEmitter() as IPushEventEmitter; - const sseHandler = SSEHandlerFactory(pushEmitter, log); + const sseHandler = SSEHandlerFactory(log, pushEmitter); sseClient.setEventHandler(sseHandler); // [Only for client-side] map of hashes to user keys, to dispatch MY_SEGMENTS_UPDATE events to the corresponding MySegmentsUpdateWorker diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index bda98cff..40ed56e5 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -46,7 +46,7 @@ export default function pushManagerCSFactory( // init feedback loop const pushEmitter = new platform.EventEmitter() as IPushEventEmitter; - const sseHandler = SSEHandlerFactory(pushEmitter, log); + const sseHandler = SSEHandlerFactory(log, pushEmitter); sseClient.setEventHandler(sseHandler); // [Only for client-side] map of hashes to user keys, to dispatch MY_SEGMENTS_UPDATE events to the corresponding MySegmentsUpdateWorker diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index f164ff42..ca0b519a 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -42,7 +42,7 @@ export default function pushManagerSSFactory( // init feedback loop (pushEmitter) const pushEmitter = new platform.EventEmitter() as IPushEventEmitter; - const sseHandler = SSEHandlerFactory(pushEmitter, log); + const sseHandler = SSEHandlerFactory(log, pushEmitter); sseClient.setEventHandler(sseHandler); // init workers diff --git a/src/sync/submitters/eventsSyncTask.ts b/src/sync/submitters/eventsSyncTask.ts index 9f91f2be..19859240 100644 --- a/src/sync/submitters/eventsSyncTask.ts +++ b/src/sync/submitters/eventsSyncTask.ts @@ -10,16 +10,16 @@ import { ILogger } from '../../logger/types'; * Sync task that periodically posts tracked events */ export function eventsSyncTaskFactory( + log: ILogger, postEventsBulk: IPostEventsBulk, eventsCache: IEventsCacheSync, eventsPushRate: number, eventsFirstPushWindow: number, - log: ILogger, latencyTracker?: ITimeTracker ): ISyncTask { // don't retry events. - const syncTask = submitterSyncTaskFactory(postEventsBulk, eventsCache, eventsPushRate, 'queued events', log, latencyTracker); + const syncTask = submitterSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, 'queued events', latencyTracker); // Set a timer for the first push of events, if (eventsFirstPushWindow > 0) { diff --git a/src/sync/submitters/impressionCountsSyncTask.ts b/src/sync/submitters/impressionCountsSyncTask.ts index c489bca1..a24ea41e 100644 --- a/src/sync/submitters/impressionCountsSyncTask.ts +++ b/src/sync/submitters/impressionCountsSyncTask.ts @@ -35,12 +35,12 @@ const IMPRESSIONS_COUNT_RATE = 1800000; // 30 minutes * Sync task that periodically posts impression counts */ export function impressionCountsSyncTaskFactory( + log: ILogger, postTestImpressionsCount: IPostTestImpressionsCount, impressionCountsCache: IImpressionCountsCacheSync, - log: ILogger, latencyTracker?: ITimeTracker ): ISyncTask { // retry impressions counts only once. - return submitterSyncTaskFactory(postTestImpressionsCount, impressionCountsCache, IMPRESSIONS_COUNT_RATE, 'impression counts', log, latencyTracker, fromImpressionCountsCollector, 1); + return submitterSyncTaskFactory(log, postTestImpressionsCount, impressionCountsCache, IMPRESSIONS_COUNT_RATE, 'impression counts', latencyTracker, fromImpressionCountsCollector, 1); } diff --git a/src/sync/submitters/impressionsSyncTask.ts b/src/sync/submitters/impressionsSyncTask.ts index fd4b20b8..c5ff1d02 100644 --- a/src/sync/submitters/impressionsSyncTask.ts +++ b/src/sync/submitters/impressionsSyncTask.ts @@ -41,14 +41,14 @@ export function fromImpressionsCollector(sendLabels: boolean, data: ImpressionDT * Sync task that periodically posts impressions data */ export function impressionsSyncTaskFactory( + log: ILogger, postTestImpressionsBulk: IPostTestImpressionsBulk, impressionsCache: IImpressionsCacheSync, impressionsRefreshRate: number, sendLabels = false, - log: ILogger, latencyTracker?: ITimeTracker, ): ISyncTask { // retry impressions only once. - return submitterSyncTaskFactory(postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, 'impressions', log, latencyTracker, fromImpressionsCollector.bind(undefined, sendLabels), 1); + return submitterSyncTaskFactory(log, postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, 'impressions', latencyTracker, fromImpressionsCollector.bind(undefined, sendLabels), 1); } diff --git a/src/sync/submitters/metricsSyncTask.ts b/src/sync/submitters/metricsSyncTask.ts index 6f1cf4ad..2f743884 100644 --- a/src/sync/submitters/metricsSyncTask.ts +++ b/src/sync/submitters/metricsSyncTask.ts @@ -23,27 +23,27 @@ function fromCache(propertyName: 'latencies' | 'delta') { * Sync task that periodically posts telemetry counts */ export function countsSyncTaskFactory( + log: ILogger, postMetricsCounters: IPostMetricsCounters, countsCache: ICountsCacheSync, metricsRefreshRate: number, - log: ILogger, latencyTracker?: ITimeTracker ): ISyncTask { - return submitterSyncTaskFactory(postMetricsCounters, countsCache, metricsRefreshRate, 'count metrics', log, latencyTracker, fromCache('delta')); + return submitterSyncTaskFactory(log, postMetricsCounters, countsCache, metricsRefreshRate, 'count metrics', latencyTracker, fromCache('delta')); } /** * Sync task that periodically posts telemetry latencies */ export function latenciesSyncTaskFactory( + log: ILogger, postMetricsLatencies: IPostMetricsTimes, latenciesCache: ILatenciesCacheSync, metricsRefreshRate: number, - log: ILogger, latencyTracker?: ITimeTracker ): ISyncTask { // don't retry metrics. - return submitterSyncTaskFactory(postMetricsLatencies, latenciesCache, metricsRefreshRate, 'latency metrics', log, latencyTracker, fromCache('latencies')); + return submitterSyncTaskFactory(log, postMetricsLatencies, latenciesCache, metricsRefreshRate, 'latency metrics', latencyTracker, fromCache('latencies')); } diff --git a/src/sync/submitters/submitterSyncTask.ts b/src/sync/submitters/submitterSyncTask.ts index 5da26e1a..4fc01e08 100644 --- a/src/sync/submitters/submitterSyncTask.ts +++ b/src/sync/submitters/submitterSyncTask.ts @@ -9,11 +9,11 @@ import { ILogger } from '../../logger/types'; * Base function to create submitter sync tasks, such as ImpressionsSyncTask and EventsSyncTask */ export function submitterSyncTaskFactory( + log: ILogger, postClient: (body: string) => Promise, sourceCache: IRecorderCacheConsumerSync, postRate: number, dataName: string, - log: ILogger, latencyTracker?: ITimeTracker, fromCacheToPayload?: (cacheData: TState) => any, maxRetries: number = 0, @@ -53,5 +53,5 @@ export function submitterSyncTaskFactory( return latencyTrackerStop ? postPromise.then(latencyTrackerStop).catch(latencyTrackerStop) : postPromise; } - return syncTaskFactory(postData, postRate, dataName + ' submitter', log); + return syncTaskFactory(log, postData, postRate, dataName + ' submitter'); } diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index d85ed161..6ef0c675 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -48,11 +48,11 @@ export function syncManagerOnlineFactory( /** Submitter Manager */ // It is not inyected via a factory as push and polling managers, because at the moment it is mandatory and the same for server-side and client-side variants const submitters = [ - impressionsSyncTaskFactory(splitApi.postTestImpressionsBulk, storage.impressions, settings.scheduler.impressionsRefreshRate, settings.core.labelsEnabled, log), - eventsSyncTaskFactory(splitApi.postEventsBulk, storage.events, settings.scheduler.eventsPushRate, settings.startup.eventsFirstPushWindow, log) + impressionsSyncTaskFactory(log, splitApi.postTestImpressionsBulk, storage.impressions, settings.scheduler.impressionsRefreshRate, settings.core.labelsEnabled), + eventsSyncTaskFactory(log, splitApi.postEventsBulk, storage.events, settings.scheduler.eventsPushRate, settings.startup.eventsFirstPushWindow) // @TODO add telemetry submitter ]; - if (storage.impressionCounts) submitters.push(impressionCountsSyncTaskFactory(splitApi.postTestImpressionsCount, storage.impressionCounts, log)); + if (storage.impressionCounts) submitters.push(impressionCountsSyncTaskFactory(log, splitApi.postTestImpressionsCount, storage.impressionCounts)); const submitter = syncTaskComposite(submitters); diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index ea74759e..ed0c16e9 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -6,7 +6,7 @@ import { ISyncTask } from './types'; /** * factory of sync tasks */ -export default function syncTaskFactory(task: (...args: Input) => Promise, period: number, taskName = 'task', log: ILogger): ISyncTask { +export default function syncTaskFactory(log: ILogger, task: (...args: Input) => Promise, period: number, taskName = 'task'): ISyncTask { // flag that indicates if the task is being executed let executing = false; diff --git a/src/utils/timeTracker/__tests__/index.spec.ts b/src/utils/timeTracker/__tests__/index.spec.ts index 45fcf05e..d9348e27 100644 --- a/src/utils/timeTracker/__tests__/index.spec.ts +++ b/src/utils/timeTracker/__tests__/index.spec.ts @@ -27,9 +27,9 @@ describe('TIME TRACKER', () => { const promise = new Promise(res => { setTimeout(res, 1000); }); - const startNormal = tracker.start(tracker.TaskNames.SDK_READY, loggerMock); - const startNormalFake = tracker.start('fakeTask3', loggerMock); - const startWithPromise = tracker.start('fakeTask4', loggerMock, undefined, promise) as Promise; + const startNormal = tracker.start(loggerMock, tracker.TaskNames.SDK_READY); + const startNormalFake = tracker.start(loggerMock, 'fakeTask3'); + const startWithPromise = tracker.start(loggerMock, 'fakeTask4', undefined, promise) as Promise; expect(typeof startNormal).toBe('function'); // If we call start without a promise, it will return the stop function, // @ts-expect-error @@ -40,14 +40,14 @@ describe('TIME TRACKER', () => { }); test('stop() / should stop the timer and return the time, if any', () => { - tracker.start('test_task', loggerMock); + tracker.start(loggerMock, 'test_task'); // creating two tasks with the same task name - const stopFromStart = tracker.start('fakeTask5', loggerMock) as () => number; - const stopFromStart2 = tracker.start('fakeTask5', loggerMock) as () => number; + const stopFromStart = tracker.start(loggerMock, 'fakeTask5') as () => number; + const stopFromStart2 = tracker.start(loggerMock, 'fakeTask5') as () => number; - const stopNotExistentTask = tracker.stop('not_existent', loggerMock); - const stopNotExistentTaskAndModifier = tracker.stop('test_task', loggerMock, 'mod'); + const stopNotExistentTask = tracker.stop(loggerMock, 'not_existent'); + const stopNotExistentTaskAndModifier = tracker.stop(loggerMock, 'test_task', 'mod'); expect(typeof stopNotExistentTask).toBe('undefined'); // If we try to stop a timer that does not exist, we get undefined. expect(typeof stopNotExistentTaskAndModifier).toBe('undefined'); // If we try to stop a timer that does not exist, we get undefined. diff --git a/src/utils/timeTracker/index.ts b/src/utils/timeTracker/index.ts index f6c61b57..329dc707 100644 --- a/src/utils/timeTracker/index.ts +++ b/src/utils/timeTracker/index.ts @@ -115,21 +115,21 @@ const TrackerAPI = { /** * "Private" method, used to attach count/countException and stop callbacks to a promise. * + * @param {ILogger} log - Logger. * @param {Promise} promise - The promise we want to attach the callbacks. * @param {string} task - The name of the task. - * @param {ILogger} log - Logger. * @param {number | string} modifier - (optional) The modifier for the task, if any. */ - __attachToPromise(promise: Promise, task: string, log: ILogger, collector: false | MetricsCollector, modifier?: number | string) { + __attachToPromise(log: ILogger, promise: Promise, task: string, collector: false | MetricsCollector, modifier?: number | string) { return promise.then(resp => { - this.stop(task, log, modifier); + this.stop(log, task, modifier); if (collector && collector.count) collector.count(resp.status); return resp; }) .catch(err => { - this.stop(task, log, modifier); + this.stop(log, task, modifier); if (collector && collector.countException) collector.countException(); @@ -140,13 +140,13 @@ const TrackerAPI = { * Starts tracking the time for a given task. All tasks tracked are considered "unique" because * there may be multiple SDK instances tracking a "generic" task, making any task non-generic. * - * @param {string} task - The task we are starting. * @param {ILogger} log - Logger. + * @param {string} task - The task we are starting. * @param {Object} collectors - The collectors map. * @param {Promise} promise - (optional) The promise we are tracking. * @return {Function | Promise} The stop function for this specific task or the promise received with the callbacks registered. */ - start(task: string, log: ILogger, collectors?: Record, promise?: Promise, now?: () => number): Promise | (() => number) { + start(log: ILogger, task: string, collectors?: Record, promise?: Promise, now?: () => number): Promise | (() => number) { const taskUniqueId = uniqueId(); const taskCollector = getCollectorForTask(task, collectors); let result; @@ -154,10 +154,10 @@ const TrackerAPI = { // If we are registering a promise with this task, we should count the status and the exceptions as well // as stopping the task when the promise resolves. Then return the promise if (thenable(promise)) { - result = this.__attachToPromise(promise, task, log, taskCollector, taskUniqueId); + result = this.__attachToPromise(log, promise, task, taskCollector, taskUniqueId); } else { // If not, we return the stop function, as it will be stopped manually. - result = this.stop.bind(this, task, log, taskUniqueId); + result = this.stop.bind(this, log, task, taskUniqueId); if (CALLBACKS[task] && !taskCollector) { // and provide a way for a defered setup of the collector, if needed. // @ts-expect-error @@ -193,17 +193,17 @@ const TrackerAPI = { /** * Stops the tracking of a given task. * - * @param {string} task - The task we are starting. * @param {ILogger} log - Logger. + * @param {string} task - The task we are starting. * @param {number | string} modifier - (optional) The modifier for that specific task. */ - stop(task: string, log: ILogger, modifier?: number | string) { + stop(log: ILogger, task: string, modifier?: number | string) { const timerName = generateTimerKey(task, modifier); const timerData = timers[timerName]; if (timerData) { // Stop the timer and round result for readability. const et = timerData.timer(); - log.debug(`[${task}] took ${et}ms to finish.`); + log.debug(`time tracker: [${task}] took ${et}ms to finish.`); // Check if we have a tracker callback. if (timerData.cb) { From 09cc2063e38ff461896cd24e830f97b80436ff06 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 10 Mar 2021 19:03:32 -0300 Subject: [PATCH 23/58] added setLogLevel method to logger --- src/logger/__tests__/index.spec.ts | 5 +++-- src/logger/__tests__/sdkLogger.mock.ts | 4 ++-- src/logger/__tests__/sdkLogger.spec.ts | 8 ++++---- src/logger/index.ts | 7 ++++++- src/logger/sdkLogger.ts | 2 +- src/logger/types.ts | 2 +- src/utils/settingsValidation/logger/pluggableLogger.ts | 4 ++-- 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index e9f8ffdc..cfb95331 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -33,7 +33,8 @@ test('SPLIT LOGGER / Logger class shape', () => { expect(typeof logger.info).toBe('function'); // instance.info should be a method. expect(typeof logger.warn).toBe('function'); // instance.warn should be a method. expect(typeof logger.error).toBe('function'); // instance.error should be a method. - expect(typeof logger.options.logLevel).toBe('string'); // instance.options.logLevel should be a string. + expect(typeof logger.setLogLevel).toBe('function'); // @ts-ignore // instance.setLogLevel should be a method. + expect(typeof logger.options.logLevel).toBe('string'); // @ts-ignore // instance.options.logLevel should be a string. expect(typeof logger.options.showLevel).toBe('boolean'); // instance.options.showLevel should be a boolean. }); @@ -66,7 +67,7 @@ function testLogLevels(levelToTest: LogLevel) { const expectedMessage = buildExpectedMessage(levelToTest, logCategory, logMsg, showLevel); // Set the logLevel for this iteration. - instance.options.logLevel = LogLevels[logLevel]; + instance.setLogLevel(LogLevels[logLevel]); // Call the method // @ts-ignore instance[logMethod](logMsg); diff --git a/src/logger/__tests__/sdkLogger.mock.ts b/src/logger/__tests__/sdkLogger.mock.ts index d8f895d8..7d846a2e 100644 --- a/src/logger/__tests__/sdkLogger.mock.ts +++ b/src/logger/__tests__/sdkLogger.mock.ts @@ -1,11 +1,10 @@ -import { ILoggerOptions } from '../types'; export const loggerMock = { warn: jest.fn(), error: jest.fn(), debug: jest.fn(), info: jest.fn(), - options: { logLevel: 'NONE', showLevel: true } as ILoggerOptions + setLogLevel: jest.fn() }; export function mockClear() { @@ -13,4 +12,5 @@ export function mockClear() { loggerMock.error.mockClear(); loggerMock.debug.mockClear(); loggerMock.info.mockClear(); + loggerMock.setLogLevel.mockClear(); } diff --git a/src/logger/__tests__/sdkLogger.spec.ts b/src/logger/__tests__/sdkLogger.spec.ts index ce716e71..230861a1 100644 --- a/src/logger/__tests__/sdkLogger.spec.ts +++ b/src/logger/__tests__/sdkLogger.spec.ts @@ -11,18 +11,18 @@ test('createLoggerAPI / methods and props', () => { expect(typeof loggerAPI).toBe('object'); // Our logger should expose an API object. expect(typeof loggerAPI.setLogLevel).toBe('function'); // API object should have setLogLevel method. - loggerAPI.setLogLevel('INFO'); + loggerAPI.setLogLevel('INFO'); // @ts-ignore expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel should update the log level. // @ts-ignore - loggerAPI.setLogLevel('warn'); + loggerAPI.setLogLevel('warn'); // @ts-ignore expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel with an invalid value should not update the log level. expect(typeof loggerAPI.enable).toBe('function'); // API object should have enable method. - loggerAPI.enable(); + loggerAPI.enable(); // @ts-ignore expect(logger.options.logLevel).toBe('DEBUG'); // calling enable should update logger log level to DEBUG. expect(typeof loggerAPI.disable).toBe('function'); // API object should have disable method. - loggerAPI.disable(); + loggerAPI.disable(); // @ts-ignore expect(logger.options.logLevel).toBe('NONE'); // calling disable should update logger log level to NONE. expect(loggerAPI.LogLevel).toEqual(LogLevels); // API object should have LogLevel prop including all available levels. diff --git a/src/logger/index.ts b/src/logger/index.ts index f7fd7959..9b813191 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -21,14 +21,19 @@ const defaultOptions = { }; export class Logger implements ILogger { + private category: string; - public options: Required; + private options: Required; constructor(category: string, options?: ILoggerOptions) { this.category = category; this.options = objectAssign({}, defaultOptions, options); } + setLogLevel(logLevel: LogLevel) { + this.options.logLevel = logLevel; + } + debug(msg: string) { this._log(LogLevels.DEBUG, msg); } diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 4c98269f..2bb3c7b1 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -13,7 +13,7 @@ export function createLoggerAPI(log: ILogger): ILoggerAPI { function setLogLevel(logLevel: string) { if (isLogLevelString(logLevel)) { - log.options.logLevel = logLevel; + log.setLogLevel(logLevel); } else { log.error('Invalid Log Level - No changes to the logs will be applied.'); } diff --git a/src/logger/types.ts b/src/logger/types.ts index b8f08302..923988e0 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -6,7 +6,7 @@ export interface ILoggerOptions { } export interface ILogger { - options: ILoggerOptions + setLogLevel(logLevel: LogLevel): void debug(msg: string): void diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index 52e38712..4ae66f49 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -1,7 +1,7 @@ import { ILogger } from '../../../logger/types'; const noopLogger: ILogger = { - options: { logLevel: 'NONE' }, + setLogLevel() { }, debug() { }, info() { }, warn() { }, @@ -10,7 +10,7 @@ const noopLogger: ILogger = { function isLogger(log: unknown): log is ILogger { // @ts-ignore - return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function'; + return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function' && typeof log.setLogLevel === 'function'; } /** From 71c59c1974a63ca94fe5b3ba90bb2a9c3bd10182 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 10 Mar 2021 19:25:48 -0300 Subject: [PATCH 24/58] using constants to extract string literals into separete files --- src/evaluator/combiners/and.ts | 3 +- src/evaluator/combiners/ifelseif.ts | 7 +- src/evaluator/condition/engineUtils.ts | 3 +- src/evaluator/matchers/all.ts | 3 +- src/evaluator/matchers/between.ts | 3 +- src/evaluator/matchers/boolean.ts | 3 +- src/evaluator/matchers/cont_all.ts | 3 +- src/evaluator/matchers/cont_any.ts | 3 +- src/evaluator/matchers/cont_str.ts | 3 +- src/evaluator/matchers/dependency.ts | 5 +- src/evaluator/matchers/eq.ts | 3 +- src/evaluator/matchers/eq_set.ts | 3 +- src/evaluator/matchers/ew.ts | 3 +- src/evaluator/matchers/gte.ts | 3 +- src/evaluator/matchers/lte.ts | 3 +- src/evaluator/matchers/part_of.ts | 3 +- src/evaluator/matchers/segment.ts | 5 +- src/evaluator/matchers/string.ts | 5 +- src/evaluator/matchers/sw.ts | 3 +- src/evaluator/matchers/whitelist.ts | 3 +- src/evaluator/value/index.ts | 7 +- src/evaluator/value/sanitize.ts | 3 +- src/listeners/browser.ts | 5 +- src/listeners/node.ts | 9 +- src/logger/browser/debugLogger.ts | 8 ++ src/logger/browser/errorLogger.ts | 5 + src/logger/browser/infoLogger.ts | 7 ++ src/logger/browser/warnLogger.ts | 6 + src/logger/codesConstants.ts | 118 ++++++++++++++++++ src/logger/codesConstantsBrowser.ts | 3 + src/logger/codesConstantsNode.ts | 21 ++++ src/logger/codesDebug.ts | 44 +++++++ src/logger/codesDebugBrowser.ts | 6 + src/logger/codesDebugNode.ts | 14 +++ src/logger/codesError.ts | 36 ++++++ src/logger/codesErrorNode.ts | 7 ++ src/logger/codesInfo.ts | 26 ++++ src/logger/codesWarn.ts | 28 +++++ src/logger/codesWarnNode.ts | 5 + src/logger/sdkLogger.ts | 3 +- src/readiness/sdkReadinessManager.ts | 9 +- src/sdkClient/client.ts | 5 +- src/sdkClient/sdkClientMethod.ts | 3 +- src/sdkClient/sdkClientMethodCS.ts | 7 +- src/sdkClient/sdkClientMethodCSWithTT.ts | 7 +- src/sdkFactory/index.ts | 7 +- src/services/splitHttpClient.ts | 5 +- .../splitsParser/splitsParserFromFile.ts | 9 +- .../offline/syncTasks/fromObjectSyncTask.ts | 5 +- src/sync/polling/pollingManagerCS.ts | 7 +- src/sync/polling/pollingManagerSS.ts | 10 +- .../polling/syncTasks/mySegmentsSyncTask.ts | 3 +- .../polling/syncTasks/segmentsSyncTask.ts | 9 +- src/sync/polling/syncTasks/splitsSyncTask.ts | 13 +- src/sync/streaming/SSEHandler/index.ts | 9 +- src/sync/streaming/pushManager.ts | 15 +-- src/sync/streaming/pushManagerCS.ts | 15 +-- src/sync/streaming/pushManagerSS.ts | 15 +-- src/sync/submitters/eventsSyncTask.ts | 3 +- src/sync/submitters/submitterSyncTask.ts | 9 +- src/sync/syncManagerOnline.ts | 7 +- src/sync/syncTask.ts | 7 +- src/trackers/eventTracker.ts | 5 +- src/trackers/impressionsTracker.ts | 7 +- src/utils/inputValidation/attributes.ts | 3 +- src/utils/inputValidation/event.ts | 9 +- src/utils/inputValidation/eventProperties.ts | 9 +- src/utils/inputValidation/eventValue.ts | 3 +- src/utils/inputValidation/isOperational.ts | 5 +- src/utils/inputValidation/key.ts | 13 +- src/utils/inputValidation/split.ts | 9 +- src/utils/inputValidation/splitExistance.ts | 3 +- src/utils/inputValidation/splits.ts | 3 +- src/utils/inputValidation/trafficType.ts | 9 +- .../inputValidation/trafficTypeExistance.ts | 3 +- .../settingsValidation/impressionsMode.ts | 3 +- .../settingsValidation/integrations/common.ts | 3 +- src/utils/settingsValidation/splitFilters.ts | 9 +- .../settingsValidation/storage/storageCS.ts | 3 +- 79 files changed, 554 insertions(+), 155 deletions(-) create mode 100644 src/logger/browser/debugLogger.ts create mode 100644 src/logger/browser/errorLogger.ts create mode 100644 src/logger/browser/infoLogger.ts create mode 100644 src/logger/browser/warnLogger.ts create mode 100644 src/logger/codesConstants.ts create mode 100644 src/logger/codesConstantsBrowser.ts create mode 100644 src/logger/codesConstantsNode.ts create mode 100644 src/logger/codesDebug.ts create mode 100644 src/logger/codesDebugBrowser.ts create mode 100644 src/logger/codesDebugNode.ts create mode 100644 src/logger/codesError.ts create mode 100644 src/logger/codesErrorNode.ts create mode 100644 src/logger/codesInfo.ts create mode 100644 src/logger/codesWarn.ts create mode 100644 src/logger/codesWarnNode.ts diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index 7f9b43c7..6549594e 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -5,6 +5,7 @@ import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { MaybeThenable } from '../../dtos/types'; import { IMatcher } from '../types'; +import { DEBUG_0 } from '../../logger/codesConstants'; export default function andCombinerContext(log: ILogger, matchers: IMatcher[]) { @@ -12,7 +13,7 @@ export default function andCombinerContext(log: ILogger, matchers: IMatcher[]) { // Array.prototype.every is supported by target environments const hasMatchedAll = results.every(value => value); - log.debug(`[andCombiner] evaluates to ${hasMatchedAll}`); + log.debug(DEBUG_0, [hasMatchedAll]); return hasMatchedAll; } diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index 23f45183..a680cb13 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -7,11 +7,12 @@ import * as LabelsConstants from '../../utils/labels'; import { CONTROL } from '../../utils/constants'; import { SplitIO } from '../../types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; +import { DEBUG_1, DEBUG_2, ERROR_0 } from '../../logger/codesConstants'; export default function ifElseIfCombinerContext(log: ILogger, predicates: IEvaluator[]): IEvaluator { function unexpectedInputHandler() { - log.error('Invalid Split provided, no valid conditions found'); + log.error(ERROR_0); return { treatment: CONTROL, @@ -26,13 +27,13 @@ export default function ifElseIfCombinerContext(log: ILogger, predicates: IEvalu const evaluation = predicateResults[i]; if (evaluation !== undefined) { - log.debug(`Treatment found: ${evaluation.treatment}`); + log.debug(DEBUG_1, [evaluation.treatment]); return evaluation; } } - log.debug('All predicates evaluated, no treatment found.'); + log.debug(DEBUG_2); return undefined; } diff --git a/src/evaluator/condition/engineUtils.ts b/src/evaluator/condition/engineUtils.ts index be0b4fc9..da1e024b 100644 --- a/src/evaluator/condition/engineUtils.ts +++ b/src/evaluator/condition/engineUtils.ts @@ -1,3 +1,4 @@ +import { DEBUG_3 } from '../../logger/codesConstants'; import { ILogger } from '../../logger/types'; import { bucket } from '../../utils/murmur3/murmur3'; // import { logFactory } from '../../logger/sdkLogger'; @@ -11,7 +12,7 @@ export function getTreatment(log: ILogger, key: string, seed: number, treatments const treatment = treatments.getTreatmentFor(_bucket); - log.debug(`[engine] using algo 'murmur' bucket ${_bucket} for key ${key} using seed ${seed} - treatment ${treatment}`); + log.debug(DEBUG_3, [_bucket, key, seed, treatment]); return treatment; } diff --git a/src/evaluator/matchers/all.ts b/src/evaluator/matchers/all.ts index 6e40c319..ca78a5d2 100644 --- a/src/evaluator/matchers/all.ts +++ b/src/evaluator/matchers/all.ts @@ -1,10 +1,11 @@ +import { DEBUG_4 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; export default function allMatcherContext(log: ILogger) { return function allMatcher(runtimeAttr: string): boolean { - log.debug('[allMatcher] is always true'); + log.debug(DEBUG_4); return runtimeAttr != null; }; diff --git a/src/evaluator/matchers/between.ts b/src/evaluator/matchers/between.ts index db2cbb3a..6429b12e 100644 --- a/src/evaluator/matchers/between.ts +++ b/src/evaluator/matchers/between.ts @@ -1,4 +1,5 @@ import { IBetweenMatcherData } from '../../dtos/types'; +import { DEBUG_5 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -8,7 +9,7 @@ export default function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatc let isBetween = runtimeAttr >= ruleVO.start && runtimeAttr <= ruleVO.end; - log.debug(`[betweenMatcher] is ${runtimeAttr} between ${ruleVO.start} and ${ruleVO.end}? ${isBetween}`); + log.debug(DEBUG_5, [runtimeAttr, ruleVO.start, ruleVO.end, isBetween]); return isBetween; }; diff --git a/src/evaluator/matchers/boolean.ts b/src/evaluator/matchers/boolean.ts index d47befd5..67ba6645 100644 --- a/src/evaluator/matchers/boolean.ts +++ b/src/evaluator/matchers/boolean.ts @@ -1,3 +1,4 @@ +import { DEBUG_6 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -6,7 +7,7 @@ export default function booleanMatcherContext(log: ILogger, ruleAttr: boolean) / return function booleanMatcher(runtimeAttr: boolean): boolean { let booleanMatches = ruleAttr === runtimeAttr; - log.debug(`[booleanMatcher] ${ruleAttr} === ${runtimeAttr}`); + log.debug(DEBUG_6, [ruleAttr, runtimeAttr]); return booleanMatches; }; diff --git a/src/evaluator/matchers/cont_all.ts b/src/evaluator/matchers/cont_all.ts index 48fcceb8..d292b7a4 100644 --- a/src/evaluator/matchers/cont_all.ts +++ b/src/evaluator/matchers/cont_all.ts @@ -1,3 +1,4 @@ +import { DEBUG_7 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -16,7 +17,7 @@ export default function containsAllMatcherContext(log: ILogger, ruleAttr: string } } - log.debug(`[containsAllMatcher] ${runtimeAttr} contains all elements of ${ruleAttr}? ${containsAll}`); + log.debug(DEBUG_7, [runtimeAttr, ruleAttr, containsAll]); return containsAll; }; diff --git a/src/evaluator/matchers/cont_any.ts b/src/evaluator/matchers/cont_any.ts index 1a606dbe..f131c103 100644 --- a/src/evaluator/matchers/cont_any.ts +++ b/src/evaluator/matchers/cont_any.ts @@ -1,3 +1,4 @@ +import { DEBUG_8 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -11,7 +12,7 @@ export default function containsAnyMatcherContext(log: ILogger, ruleAttr: string if (findIndex(runtimeAttr, e => e === ruleAttr[i]) >= 0) containsAny = true; } - log.debug(`[containsAnyMatcher] ${runtimeAttr} contains at least an element of ${ruleAttr}? ${containsAny}`); + log.debug(DEBUG_8, [runtimeAttr, ruleAttr, containsAny]); return containsAny; }; diff --git a/src/evaluator/matchers/cont_str.ts b/src/evaluator/matchers/cont_str.ts index 5aad4dd2..85231cd3 100644 --- a/src/evaluator/matchers/cont_str.ts +++ b/src/evaluator/matchers/cont_str.ts @@ -2,12 +2,13 @@ import { isString } from '../../utils/lang'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; +import { DEBUG_9 } from '../../logger/codesConstants'; export default function containsStringMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function containsStringMatcher(runtimeAttr: string): boolean { let contains = ruleAttr.some(e => isString(runtimeAttr) && runtimeAttr.indexOf(e) > -1); - log.debug(`[containsStringMatcher] ${runtimeAttr} contains ${ruleAttr}? ${contains}`); + log.debug(DEBUG_9, [runtimeAttr, ruleAttr, contains]); return contains; }; diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index 6292d79e..28dc8fa2 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -5,6 +5,7 @@ import { IStorageAsync, IStorageSync } from '../../storages/types'; import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { IDependencyMatcherValue, IEvaluation, ISplitEvaluator } from '../types'; +import { DEBUG_10, DEBUG_11 } from '../../logger/codesConstants'; export default function dependencyMatcherContext(log: ILogger, { split, treatments }: IDependencyMatcherData, storage: IStorageSync | IStorageAsync) { @@ -15,13 +16,13 @@ export default function dependencyMatcherContext(log: ILogger, { split, treatmen matches = acceptableTreatments.indexOf(evaluation.treatment as string) !== -1; } - log.debug(`[dependencyMatcher] Parent split "${parentName}" evaluated to "${evaluation.treatment}" with label "${evaluation.label}". ${parentName} evaluated treatment is part of [${acceptableTreatments}] ? ${matches}.`); + log.debug(DEBUG_10, [parentName, evaluation.treatment, evaluation.label, parentName, acceptableTreatments, matches]); return matches; } return function dependencyMatcher({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator): MaybeThenable { - log.debug(`[dependencyMatcher] will evaluate parent split: "${split}" with key: ${JSON.stringify(key)} ${attributes ? '\n attributes: ' + JSON.stringify(attributes) : ''}`); + log.debug(DEBUG_11, [split, JSON.stringify(key), attributes ? '\n attributes: ' + JSON.stringify(attributes) : '']); const evaluation = splitEvaluator(log, key, split, attributes, storage); if (thenable(evaluation)) { diff --git a/src/evaluator/matchers/eq.ts b/src/evaluator/matchers/eq.ts index 891c42f6..fdd91f7a 100644 --- a/src/evaluator/matchers/eq.ts +++ b/src/evaluator/matchers/eq.ts @@ -1,3 +1,4 @@ +import { DEBUG_12 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -6,7 +7,7 @@ export default function equalToMatcherContext(log: ILogger, ruleAttr: number) /* return function equalToMatcher(runtimeAttr: number): boolean { let isEqual = runtimeAttr === ruleAttr; - log.debug(`[equalToMatcher] is ${runtimeAttr} equal to ${ruleAttr}? ${isEqual}`); + log.debug(DEBUG_12, [runtimeAttr, ruleAttr, isEqual]); return isEqual; }; diff --git a/src/evaluator/matchers/eq_set.ts b/src/evaluator/matchers/eq_set.ts index 88b4bb63..7b700789 100644 --- a/src/evaluator/matchers/eq_set.ts +++ b/src/evaluator/matchers/eq_set.ts @@ -1,3 +1,4 @@ +import { DEBUG_13 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -13,7 +14,7 @@ export default function equalToSetMatcherContext(log: ILogger, ruleAttr: string[ if (findIndex(ruleAttr, e => e === runtimeAttr[i]) < 0) isEqual = false; } - log.debug(`[equalToSetMatcher] is ${runtimeAttr} equal to set ${ruleAttr}? ${isEqual}`); + log.debug(DEBUG_13, [runtimeAttr, ruleAttr, isEqual]); return isEqual; }; diff --git a/src/evaluator/matchers/ew.ts b/src/evaluator/matchers/ew.ts index 7b8df448..f14d4088 100644 --- a/src/evaluator/matchers/ew.ts +++ b/src/evaluator/matchers/ew.ts @@ -1,3 +1,4 @@ +import { DEBUG_14 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -7,7 +8,7 @@ export default function endsWithMatcherContext(log: ILogger, ruleAttr: string[]) return function endsWithMatcher(runtimeAttr: string): boolean { let endsWith = ruleAttr.some(e => strEndsWith(runtimeAttr, e)); - log.debug(`[endsWithMatcher] ${runtimeAttr} ends with ${ruleAttr}? ${endsWith}`); + log.debug(DEBUG_14, [runtimeAttr, ruleAttr, endsWith]); return endsWith; }; diff --git a/src/evaluator/matchers/gte.ts b/src/evaluator/matchers/gte.ts index 0d147c95..30d81722 100644 --- a/src/evaluator/matchers/gte.ts +++ b/src/evaluator/matchers/gte.ts @@ -1,3 +1,4 @@ +import { DEBUG_15 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -6,7 +7,7 @@ export default function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: n return function greaterThanEqualMatcher(runtimeAttr: number): boolean { let isGreaterEqualThan = runtimeAttr >= ruleAttr; - log.debug(`[greaterThanEqualMatcher] is ${runtimeAttr} greater than ${ruleAttr}? ${isGreaterEqualThan}`); + log.debug(DEBUG_15, [runtimeAttr, ruleAttr, isGreaterEqualThan]); return isGreaterEqualThan; }; diff --git a/src/evaluator/matchers/lte.ts b/src/evaluator/matchers/lte.ts index 95808a74..ba69e68d 100644 --- a/src/evaluator/matchers/lte.ts +++ b/src/evaluator/matchers/lte.ts @@ -1,3 +1,4 @@ +import { DEBUG_16 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -6,7 +7,7 @@ export default function lessThanEqualMatcherContext(log: ILogger, ruleAttr: numb return function lessThanEqualMatcher(runtimeAttr: number): boolean { let isLessEqualThan = runtimeAttr <= ruleAttr; - log.debug(`[lessThanEqualMatcher] is ${runtimeAttr} less than ${ruleAttr}? ${isLessEqualThan}`); + log.debug(DEBUG_16, [runtimeAttr, ruleAttr, isLessEqualThan]); return isLessEqualThan; }; diff --git a/src/evaluator/matchers/part_of.ts b/src/evaluator/matchers/part_of.ts index c0218818..d4aaed73 100644 --- a/src/evaluator/matchers/part_of.ts +++ b/src/evaluator/matchers/part_of.ts @@ -2,6 +2,7 @@ import { findIndex } from '../../utils/lang'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; +import { DEBUG_17 } from '../../logger/codesConstants'; export default function partOfMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function partOfMatcher(runtimeAttr: string[]): boolean { @@ -13,7 +14,7 @@ export default function partOfMatcherContext(log: ILogger, ruleAttr: string[]) / if (findIndex(ruleAttr, e => e === runtimeAttr[i]) < 0) isPartOf = false; } - log.debug(`[partOfMatcher] ${runtimeAttr} is part of ${ruleAttr}? ${isPartOf}`); + log.debug(DEBUG_17, [runtimeAttr, ruleAttr, isPartOf]); return isPartOf; }; diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index 7834f57a..3b8216aa 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -4,6 +4,7 @@ import { ISegmentsCacheBase } from '../../storages/types'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; +import { DEBUG_18, DEBUG_19 } from '../../logger/codesConstants'; export default function matcherSegmentContext(log: ILogger, segmentName: string, storage: { segments: ISegmentsCacheBase }) { @@ -12,12 +13,12 @@ export default function matcherSegmentContext(log: ILogger, segmentName: string, if (thenable(isInSegment)) { isInSegment.then(result => { - log.debug(`[asyncSegmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); + log.debug(DEBUG_18, [segmentName, key, isInSegment]); return result; }); } else { - log.debug(`[segmentMatcher] evaluated ${segmentName} / ${key} => ${isInSegment}`); + log.debug(DEBUG_19, [segmentName, key, isInSegment]); } return isInSegment; diff --git a/src/evaluator/matchers/string.ts b/src/evaluator/matchers/string.ts index 8d437f79..8a301fdc 100644 --- a/src/evaluator/matchers/string.ts +++ b/src/evaluator/matchers/string.ts @@ -1,3 +1,4 @@ +import { DEBUG_21, DEBUG_20 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -9,14 +10,14 @@ export default function stringMatcherContext(log: ILogger, ruleAttr: string) /*: try { re = new RegExp(ruleAttr); } catch (e) { - log.debug(`[stringMatcher] ${ruleAttr} is an invalid regex`); + log.debug(DEBUG_21, [ruleAttr]); return false; } let regexMatches = re.test(runtimeAttr); - log.debug(`[stringMatcher] does ${runtimeAttr} matches with ${ruleAttr}? ${regexMatches ? 'yes' : 'no'}`); + log.debug(DEBUG_20, [runtimeAttr, ruleAttr, regexMatches ? 'yes' : 'no']); return regexMatches; }; diff --git a/src/evaluator/matchers/sw.ts b/src/evaluator/matchers/sw.ts index a5422b0a..1a19ff75 100644 --- a/src/evaluator/matchers/sw.ts +++ b/src/evaluator/matchers/sw.ts @@ -1,3 +1,4 @@ +import { DEBUG_22 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; @@ -7,7 +8,7 @@ export default function startsWithMatcherContext(log: ILogger, ruleAttr: string[ return function startsWithMatcher(runtimeAttr: string): boolean { let matches = ruleAttr.some(e => startsWith(runtimeAttr, e)); - log.debug(`[startsWithMatcher] ${runtimeAttr} starts with ${ruleAttr}? ${matches}`); + log.debug(DEBUG_22, [runtimeAttr, ruleAttr, matches]); return matches; }; diff --git a/src/evaluator/matchers/whitelist.ts b/src/evaluator/matchers/whitelist.ts index 735a6cb5..b45dc8b8 100644 --- a/src/evaluator/matchers/whitelist.ts +++ b/src/evaluator/matchers/whitelist.ts @@ -2,12 +2,13 @@ import { setToArray, ISet } from '../../utils/lang/sets'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; +import { DEBUG_23 } from '../../logger/codesConstants'; export default function whitelistMatcherContext(log: ILogger, ruleAttr: ISet) /*: Function */ { return function whitelistMatcher(runtimeAttr: string): boolean { let isInWhitelist = ruleAttr.has(runtimeAttr); - log.debug(`[whitelistMatcher] evaluated ${runtimeAttr} in [${setToArray(ruleAttr).join(',')}] => ${isInWhitelist}`); + log.debug(DEBUG_23, [runtimeAttr, setToArray(ruleAttr).join(','), isInWhitelist]); return isInWhitelist; }; diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index 774c353f..12d3b9c1 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -4,15 +4,16 @@ import { IMatcherDto } from '../types'; // const log = logFactory('splitio-engine:value'); import { ILogger } from '../../logger/types'; import sanitizeValue from './sanitize'; +import { DEBUG_24, WARN_1, WARN_0 } from '../../logger/codesConstants'; function parseValue(log: ILogger, key: string, attributeName: string | null, attributes: SplitIO.Attributes) { let value = undefined; if (attributeName) { if (attributes) { value = attributes[attributeName]; - log.debug(`Extracted attribute [${attributeName}], [${value}] will be used for matching.`); + log.debug(DEBUG_24, [attributeName, value]); } else { - log.warn(`Defined attribute [${attributeName}], no attributes received.`); + log.warn(WARN_1, [attributeName]); } } else { value = key; @@ -32,7 +33,7 @@ export default function value(log: ILogger, key: string, matcherDto: IMatcherDto if (sanitizedValue !== undefined) { return sanitizedValue; } else { - log.warn(`Value ${valueToMatch} ${attributeName ? ' for attribute ' + attributeName : ''}doesn't match with expected type.`); + log.warn(WARN_0, [valueToMatch, attributeName ? ' for attribute ' + attributeName : '']); return; } } diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index d7c90102..d8db57a6 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -6,6 +6,7 @@ import { ILogger } from '../../logger/types'; import { isObject, uniq, toString, toNumber } from '../../utils/lang'; import { zeroSinceHH, zeroSinceSS } from '../convertions'; import { matcherTypes, dataTypes } from '../matchers/matcherTypes'; +import { DEBUG_25 } from '../../logger/codesConstants'; function sanitizeNumber(val: any): number | undefined { const num = toNumber(val); @@ -100,7 +101,7 @@ export default function sanitize(log: ILogger, matcherTypeID: number, value: str sanitizedValue = processor(sanitizedValue, attributes); } - log.debug(`Attempted to sanitize [${value}] which should be of type [${dataType}]. \n Sanitized and processed value => [${sanitizedValue instanceof Object ? JSON.stringify(sanitizedValue) : sanitizedValue}]`); + log.debug(DEBUG_25, [value, dataType, sanitizedValue instanceof Object ? JSON.stringify(sanitizedValue) : sanitizedValue]); return sanitizedValue; } diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index cf65d460..ff5910b5 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -10,6 +10,7 @@ import { ImpressionsPayload } from '../sync/submitters/types'; import { MaybeThenable } from '../dtos/types'; import { OPTIMIZED, DEBUG } from '../utils/constants'; import objectAssign from 'object-assign'; +import { DEBUG_26, DEBUG_27 } from '../logger/codesConstantsBrowser'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client:cleanup'); @@ -41,7 +42,7 @@ export default class BrowserSignalListener implements ISignalListener { */ start() { if (typeof window !== 'undefined' && window.addEventListener) { - this.settings.log.debug('Registering flush handler when unload page event is triggered.'); + this.settings.log.debug(DEBUG_26); window.addEventListener(UNLOAD_DOM_EVENT, this.flushData); } } @@ -53,7 +54,7 @@ export default class BrowserSignalListener implements ISignalListener { */ stop() { if (typeof window !== 'undefined' && window.removeEventListener) { - this.settings.log.debug('Deregistering flush handler when unload page event is triggered.'); + this.settings.log.debug(DEBUG_27); window.removeEventListener(UNLOAD_DOM_EVENT, this.flushData); } } diff --git a/src/listeners/node.ts b/src/listeners/node.ts index 0fb72f4c..ade705da 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -3,6 +3,7 @@ import { ISignalListener } from './types'; import thenable from '../utils/promise/thenable'; import { MaybeThenable } from '../dtos/types'; import { ISettings } from '../types'; +import { DEBUG_28, DEBUG_29, DEBUG_30, ERROR_1 } from '../logger/codesConstantsNode'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client:cleanup'); @@ -23,13 +24,13 @@ export default class NodeSignalListener implements ISignalListener { } start() { - this.settings.log.debug('Registering cleanup handlers.'); + this.settings.log.debug(DEBUG_28); // eslint-disable-next-line no-undef process.on('SIGTERM', this._sigtermHandler); } stop() { - this.settings.log.debug('Deregistering cleanup handlers.'); + this.settings.log.debug(DEBUG_29); // eslint-disable-next-line no-undef process.removeListener('SIGTERM', this._sigtermHandler); } @@ -47,14 +48,14 @@ export default class NodeSignalListener implements ISignalListener { process.kill(process.pid, 'SIGTERM'); }; - this.settings.log.debug('Split SDK graceful shutdown after SIGTERM.'); + this.settings.log.debug(DEBUG_30); let handlerResult = null; try { handlerResult = this.handler(); } catch (err) { - this.settings.log.error(`Error with Split graceful shutdown: ${err}`); + this.settings.log.error(ERROR_1, [err]); } if (thenable(handlerResult)) { diff --git a/src/logger/browser/debugLogger.ts b/src/logger/browser/debugLogger.ts new file mode 100644 index 00000000..5ebeb427 --- /dev/null +++ b/src/logger/browser/debugLogger.ts @@ -0,0 +1,8 @@ +import { Logger } from '../index'; +import { codesError } from '../codesError'; +import { codesWarn } from '../codesWarn'; +import { codesInfo } from '../codesInfo'; +import { codesDebug } from '../codesDebug'; +import { _Map } from '../../utils/lang/maps'; + +export const debugLogger = new Logger('splitio', { logLevel: 'DEBUG' }, new _Map(codesError.concat(codesWarn).concat(codesInfo).concat(codesDebug))); diff --git a/src/logger/browser/errorLogger.ts b/src/logger/browser/errorLogger.ts new file mode 100644 index 00000000..b132f192 --- /dev/null +++ b/src/logger/browser/errorLogger.ts @@ -0,0 +1,5 @@ +import { Logger } from '../index'; +import { codesError } from '../codesError'; +import { _Map } from '../../utils/lang/maps'; + +export const errorLogger = new Logger('splitio', { logLevel: 'ERROR' }, new _Map(codesError)); diff --git a/src/logger/browser/infoLogger.ts b/src/logger/browser/infoLogger.ts new file mode 100644 index 00000000..f001b9bb --- /dev/null +++ b/src/logger/browser/infoLogger.ts @@ -0,0 +1,7 @@ +import { Logger } from '../index'; +import { codesError } from '../codesError'; +import { codesWarn } from '../codesWarn'; +import { codesInfo } from '../codesInfo'; +import { _Map } from '../../utils/lang/maps'; + +export const infoLogger = new Logger('splitio', { logLevel: 'INFO' }, new _Map(codesError.concat(codesWarn).concat(codesInfo))); diff --git a/src/logger/browser/warnLogger.ts b/src/logger/browser/warnLogger.ts new file mode 100644 index 00000000..1ba1667b --- /dev/null +++ b/src/logger/browser/warnLogger.ts @@ -0,0 +1,6 @@ +import { Logger } from '../index'; +import { codesError } from '../codesError'; +import { codesWarn } from '../codesWarn'; +import { _Map } from '../../utils/lang/maps'; + +export const warnLogger = new Logger('splitio', { logLevel: 'WARN' }, new _Map(codesError.concat(codesWarn))); diff --git a/src/logger/codesConstants.ts b/src/logger/codesConstants.ts new file mode 100644 index 00000000..9852e7c8 --- /dev/null +++ b/src/logger/codesConstants.ts @@ -0,0 +1,118 @@ +export const DEBUG_0 = 0; +export const DEBUG_1 = 1; +export const DEBUG_2 = 2; +export const DEBUG_3 = 3; +export const DEBUG_4 = 4; +export const DEBUG_5 = 5; +export const DEBUG_6 = 6; +export const DEBUG_7 = 7; +export const DEBUG_8 = 8; +export const DEBUG_9 = 9; +export const DEBUG_10 = 10; +export const DEBUG_11 = 11; +export const DEBUG_12 = 12; +export const DEBUG_13 = 13; +export const DEBUG_14 = 14; +export const DEBUG_15 = 15; +export const DEBUG_16 = 16; +export const DEBUG_17 = 17; +export const DEBUG_18 = 18; +export const DEBUG_19 = 19; +export const DEBUG_20 = 20; +export const DEBUG_21 = 21; +export const DEBUG_22 = 22; +export const DEBUG_23 = 23; +export const DEBUG_24 = 24; +export const DEBUG_25 = 25; +export const DEBUG_31 = 31; +export const DEBUG_32 = 32; +export const DEBUG_33 = 33; +export const DEBUG_36 = 36; +export const DEBUG_42 = 42; +export const DEBUG_43 = 43; +export const DEBUG_44 = 44; +export const DEBUG_45 = 45; +export const DEBUG_46 = 46; +export const DEBUG_47 = 47; +export const DEBUG_48 = 48; +export const DEBUG_49 = 49; +export const DEBUG_50 = 50; +export const DEBUG_51 = 51; +export const INFO_0 = 100; +export const INFO_1 = 101; +export const INFO_2 = 102; +export const INFO_3 = 103; +export const INFO_4 = 104; +export const INFO_5 = 105; +export const INFO_6 = 106; +export const INFO_7 = 107; +export const INFO_8 = 108; +export const INFO_9 = 109; +export const INFO_10 = 110; +export const INFO_11 = 111; +export const INFO_12 = 112; +export const INFO_13 = 113; +export const INFO_14 = 114; +export const INFO_15 = 115; +export const INFO_16 = 116; +export const INFO_17 = 117; +export const INFO_18 = 118; +export const INFO_19 = 119; +export const INFO_20 = 120; +export const INFO_21 = 121; +export const WARN_0 = 200; +export const WARN_1 = 201; +export const WARN_2 = 202; +export const WARN_4 = 204; +export const WARN_5 = 205; +export const WARN_6 = 206; +export const WARN_7 = 207; +export const WARN_8 = 208; +export const WARN_9 = 209; +export const WARN_10 = 210; +export const WARN_11 = 211; +export const WARN_12 = 212; +export const WARN_13 = 213; +export const WARN_14 = 214; +export const WARN_15 = 215; +export const WARN_17 = 217; +export const WARN_18 = 218; +export const WARN_19 = 219; +export const WARN_20 = 220; +export const WARN_21 = 221; +export const WARN_22 = 222; +export const WARN_23 = 223; +export const WARN_24 = 224; +export const WARN_25 = 225; +export const ERROR_0 = 300; +export const ERROR_2 = 302; +export const ERROR_3 = 303; +export const ERROR_4 = 304; +export const ERROR_5 = 305; +export const ERROR_7 = 307; +export const ERROR_9 = 309; +export const ERROR_10 = 310; +export const ERROR_11 = 311; +export const ERROR_12 = 312; +export const ERROR_13 = 313; +export const ERROR_14 = 314; +export const ERROR_15 = 315; +export const ERROR_16 = 316; +export const ERROR_17 = 317; +export const ERROR_18 = 318; +export const ERROR_19 = 319; +export const ERROR_20 = 320; +export const ERROR_21 = 321; +export const ERROR_22 = 322; +export const ERROR_23 = 323; +export const ERROR_24 = 324; +export const ERROR_25 = 325; +export const ERROR_26 = 326; +export const ERROR_32 = 332; +export const ERROR_33 = 333; +export const ERROR_34 = 334; +export const ERROR_35 = 335; +export const ERROR_36 = 336; +export const ERROR_37 = 337; +export const ERROR_38 = 338; +export const ERROR_39 = 339; diff --git a/src/logger/codesConstantsBrowser.ts b/src/logger/codesConstantsBrowser.ts new file mode 100644 index 00000000..b34771d7 --- /dev/null +++ b/src/logger/codesConstantsBrowser.ts @@ -0,0 +1,3 @@ +// listeners/browser +export const DEBUG_26 = 26; +export const DEBUG_27 = 27; diff --git a/src/logger/codesConstantsNode.ts b/src/logger/codesConstantsNode.ts new file mode 100644 index 00000000..614f9c8b --- /dev/null +++ b/src/logger/codesConstantsNode.ts @@ -0,0 +1,21 @@ +// listeners/node +export const DEBUG_28 = 28; +export const DEBUG_29 = 29; +export const DEBUG_30 = 30; +export const ERROR_1 = 301; + +// sync/polling/syncTasks/segmentsSyncTask +export const DEBUG_39 = 39; +export const DEBUG_40 = 40; +export const DEBUG_41 = 41; +export const ERROR_8 = 308; + +// sync/offline/splitsParser/splitsParserFromFile +export const DEBUG_34 = 34; +export const DEBUG_35 = 35; +export const ERROR_6 = 306; +export const WARN_3 = 203; + +// sync/polling/pollingManagerSS.ts +export const DEBUG_37 = 37; +export const DEBUG_38 = 38; diff --git a/src/logger/codesDebug.ts b/src/logger/codesDebug.ts new file mode 100644 index 00000000..02ec3d84 --- /dev/null +++ b/src/logger/codesDebug.ts @@ -0,0 +1,44 @@ +import { DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_31, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_51 } from './codesConstants'; + +export const codesDebug: [number, string][] = [ + [DEBUG_0, 'splitio-engine:combiner => [andCombiner] evaluates to %s'], + [DEBUG_1, 'splitio-engine:combiner => Treatment found: %s'], + [DEBUG_2, 'splitio-engine:combiner => All predicates evaluated, no treatment found.'], + [DEBUG_3, 'splitio-engine => [engine] using algo \'murmur\' bucket %s for key %s using seed %s - treatment %s'], + [DEBUG_4, 'splitio-engine:matcher => [allMatcher] is always true'], + [DEBUG_5, 'splitio-engine:matcher => [betweenMatcher] is %s between %s and %s? %s'], + [DEBUG_6, 'splitio-engine:matcher => [booleanMatcher] %s === %s'], + [DEBUG_7, 'splitio-engine:matcher => [containsAllMatcher] %s contains all elements of %s? %s'], + [DEBUG_8, 'splitio-engine:matcher => [containsAnyMatcher] %s contains at least an element of %s? %s'], + [DEBUG_9, 'splitio-engine:matcher => [containsStringMatcher] %s contains %s? %s'], + [DEBUG_10, 'splitio-engine:matcher => [dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], + [DEBUG_11, 'splitio-engine:matcher => [dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], + [DEBUG_12, 'splitio-engine:matcher => [equalToMatcher] is %s equal to %s? %s'], + [DEBUG_13, 'splitio-engine:matcher => [equalToSetMatcher] is %s equal to set %s? %s'], + [DEBUG_14, 'splitio-engine:matcher => [endsWithMatcher] %s ends with %s? %s'], + [DEBUG_15, 'splitio-engine:matcher => [greaterThanEqualMatcher] is %s greater than %s? %s'], + [DEBUG_16, 'splitio-engine:matcher => [lessThanEqualMatcher] is %s less than %s? %s'], + [DEBUG_17, 'splitio-engine:matcher => [partOfMatcher] %s is part of %s? %s'], + [DEBUG_18, 'splitio-engine:matcher => [asyncSegmentMatcher] evaluated %s / %s => %s'], + [DEBUG_19, 'splitio-engine:matcher => [segmentMatcher] evaluated %s / %s => %s'], + [DEBUG_20, 'splitio-engine:matcher => [stringMatcher] does %s matches with %s? %s'], + [DEBUG_21, 'splitio-engine:matcher => [stringMatcher] %s is an invalid regex'], + [DEBUG_22, 'splitio-engine:matcher => [startsWithMatcher] %s starts with %s? %s'], + [DEBUG_23, 'splitio-engine:matcher => [whitelistMatcher] evaluated %s in [%s] => %s'], + [DEBUG_24, 'splitio-engine:value => Extracted attribute [%s], [%s] will be used for matching.'], + [DEBUG_25, 'splitio-engine:sanitize => Attempted to sanitize [%s] which should be of type [%s]. \n Sanitized and processed value => [%s]'], + [DEBUG_31, 'splitio => Retrieving SDK client.'], + [DEBUG_32, 'splitio => Retrieving default SDK client.'], // @TODO remove and use 'splitio => Retrieving SDK client.' + [DEBUG_33, 'splitio => Retrieving existing SDK client.'], + [DEBUG_36, 'splitio-producer:offline => Splits data: '], + [DEBUG_42, 'splitio-sync:split-changes => Spin up split update using since = %s'], + [DEBUG_43, 'splitio-sync:split-changes => New splits %s'], + [DEBUG_44, 'splitio-sync:split-changes => Removed splits %s'], + [DEBUG_45, 'splitio-sync:split-changes => Segment names collected %s'], + [DEBUG_46, 'splitio-sync:sse-handler => New SSE message received, with data: %s.'], + [DEBUG_47, 'splitio-sync:task => Starting %s. Running each %s millis'], + [DEBUG_48, 'splitio-sync:task => Running %s'], + [DEBUG_49, 'splitio-sync:task => Stopping %s'], + [DEBUG_50, 'splitio-client:impressions-tracker => Successfully stored %s impression%s.'], + [DEBUG_51, 'Factory instantiation: splits filtering criteria is \'%s\'.'] +]; diff --git a/src/logger/codesDebugBrowser.ts b/src/logger/codesDebugBrowser.ts new file mode 100644 index 00000000..3e7be5d5 --- /dev/null +++ b/src/logger/codesDebugBrowser.ts @@ -0,0 +1,6 @@ +import { DEBUG_26, DEBUG_27 } from './codesConstantsBrowser'; + +export const codesDebugBrowser: [number, string][] = [ + [DEBUG_26, 'splitio-client:cleanup => Registering flush handler when unload page event is triggered.'], + [DEBUG_27, 'splitio-client:cleanup => Deregistering flush handler when unload page event is triggered.'], +]; diff --git a/src/logger/codesDebugNode.ts b/src/logger/codesDebugNode.ts new file mode 100644 index 00000000..890d7207 --- /dev/null +++ b/src/logger/codesDebugNode.ts @@ -0,0 +1,14 @@ +import { DEBUG_28, DEBUG_29, DEBUG_30, DEBUG_39, DEBUG_40, DEBUG_41, DEBUG_34, DEBUG_35, DEBUG_37, DEBUG_38 } from './codesConstantsNode'; + +export const codesDebugNode: [number, string][] = [ + [DEBUG_28, 'splitio-client:cleanup => Registering cleanup handlers.'], + [DEBUG_29, 'splitio-client:cleanup => Deregistering cleanup handlers.'], + [DEBUG_30, 'splitio-client:cleanup => Split SDK graceful shutdown after SIGTERM.'], + [DEBUG_39, 'splitio-sync:segment-changes => Processed %s with till = %s. Added: %s. Removed: %s'], + [DEBUG_40, 'splitio-sync:segment-changes => Processing segment %s'], + [DEBUG_41, 'splitio-sync:segment-changes => Started segments update'], + [DEBUG_34, 'splitio-offline:splits-fetcher => Ignoring empty line or comment at #%s'], + [DEBUG_35, 'splitio-offline:splits-fetcher => Ignoring line since it does not have exactly two columns #%s'], + [DEBUG_37, 'splitio-sync:polling-manager => Splits will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? + [DEBUG_38, 'splitio-sync:polling-manager => Segments will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? +]; diff --git a/src/logger/codesError.ts b/src/logger/codesError.ts new file mode 100644 index 00000000..303df195 --- /dev/null +++ b/src/logger/codesError.ts @@ -0,0 +1,36 @@ +import { ERROR_0, ERROR_2, ERROR_3, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_13, ERROR_14, ERROR_15, ERROR_16, ERROR_17, ERROR_18, ERROR_19, ERROR_20, ERROR_21, ERROR_22, ERROR_23, ERROR_24, ERROR_25, ERROR_26, ERROR_32, ERROR_33, ERROR_34, ERROR_35, ERROR_36, ERROR_37, ERROR_38, ERROR_39 } from './codesConstants'; + +export const codesError: [number, string][] = [ + [ERROR_0, 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'], + [ERROR_2, 'splitio-utils:logger => Invalid Log Level - No changes to the logs will be applied.'], + [ERROR_3, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], + [ERROR_4, 'splitio => Manager instance is not available. Provide the manager module on settings.'], + [ERROR_5, 'splitio-services:service => %s The SDK will not get ready.'], + [ERROR_7, 'splitio-producer:offline => There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], + [ERROR_9, 'splitio-sync:sse-handler => Fail to connect to streaming, with error message: %s'], + [ERROR_10, 'splitio-sync:push-manager => Failed to authenticate for streaming. Error: "%s".'], + [ERROR_11, 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'], + [ERROR_12, 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'], + [ERROR_13, '%s: attributes must be a plain object.'], + [ERROR_14, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], + [ERROR_15, '%s: you passed a null or undefined event_type, event_type must be a non-empty string.'], + [ERROR_16, '%s: you passed an invalid event_type, event_type must be a non-empty string.'], + [ERROR_17, '%s: you passed an empty event_type, event_type must be a non-empty string.'], + [ERROR_18, '%s: properties must be a plain object.'], + [ERROR_19, '%s: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'], + [ERROR_20, '%s: value must be a finite number.'], + [ERROR_21, 'Client has already been destroyed - no calls possible.'], + [ERROR_22, '%s: you passed a null or undefined %s, %s must be a non-empty string.'], + [ERROR_23, '%s: %s too long, %s must be 250 characters or less.'], + [ERROR_24, '%s: you passed an invalid %s type, %s must be a non-empty string.'], + [ERROR_25, '%s: you passed an empty string, %s must be a non-empty string.'], + [ERROR_26, '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'], + [ERROR_32, '%s: you passed an invalid %s, %s must be a non-empty string.'], + [ERROR_33, '%s: you passed an empty %s, %s must be a non-empty string.'], + [ERROR_34, '%s: %s must be a non-empty array.'], + [ERROR_35, '%s: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.'], + [ERROR_36, '%s: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.'], + [ERROR_37, '%s: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.'], + [ERROR_38, 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: \'%s\' or \'%s\'. Defaulting to \'%s\' mode.'], + [ERROR_39, 'Response status is not OK. Status: %s. URL: %s. Message: %s'] +]; diff --git a/src/logger/codesErrorNode.ts b/src/logger/codesErrorNode.ts new file mode 100644 index 00000000..b56218bd --- /dev/null +++ b/src/logger/codesErrorNode.ts @@ -0,0 +1,7 @@ +import { ERROR_1, ERROR_8, ERROR_6 } from './codesConstantsNode'; + +export const codesErrorNode: [number, string][] = [ + [ERROR_1, 'splitio-client:cleanup => Error with Split graceful shutdown: %s'], + [ERROR_8, 'splitio-sync:segment-changes => Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'], + [ERROR_6, 'splitio-offline:splits-fetcher => Ignoring entry on YAML since the format is incorrect.'], +]; diff --git a/src/logger/codesInfo.ts b/src/logger/codesInfo.ts new file mode 100644 index 00000000..f19f3472 --- /dev/null +++ b/src/logger/codesInfo.ts @@ -0,0 +1,26 @@ +import { INFO_0, INFO_1, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21 } from './codesConstants'; + +export const codesInfo: [number, string][] = [ + [INFO_0, 'Split SDK is ready from cache.'], + [INFO_1, 'Split SDK is ready.'], + [INFO_2, 'splitio-client => Split: %s. Key: %s. Evaluation: %s. Label: %s'], + [INFO_3, 'splitio-client => Queueing corresponding impression.'], + [INFO_4, 'splitio => New shared client instance created.'], + [INFO_5, 'splitio => New Split SDK instance created.'], + [INFO_6, 'splitio => Manager instance retrieved.'], + [INFO_7, 'splitio-sync:polling-manager => Turning segments data polling %s.'], + [INFO_8, 'splitio-sync:polling-manager => Starting polling'], + [INFO_9, 'splitio-sync:polling-manager => Stopping polling'], + [INFO_10, 'splitio-sync:split-changes => Retrying download of splits #%s. Reason: %s'], + [INFO_11, 'splitio-sync:push-manager => Refreshing streaming token in %s seconds.'], + [INFO_12, 'splitio-sync:push-manager => Attempting to reconnect in %s seconds.'], + [INFO_13, 'splitio-sync:push-manager => Connecting to push streaming.'], + [INFO_14, 'splitio-sync:push-manager => Streaming is not available. Switching to polling mode.'], + [INFO_15, 'splitio-sync:push-manager => Disconnecting from push streaming.'], + [INFO_16, 'splitio-sync:submitters => Flushing full events queue and reseting timer.'], + [INFO_17, 'splitio-sync:submitters => Pushing %s %s.'], + [INFO_18, 'splitio-sync:sync-manager => Streaming not available. Starting periodic fetch of data.'], + [INFO_19, 'splitio-sync:sync-manager => Streaming couldn\'t connect. Continue periodic fetch of data.'], + [INFO_20, 'splitio-sync:sync-manager => PUSH (re)connected. Syncing and stopping periodic fetch of data.'], + [INFO_21, 'splitio-client:event-tracker => Successfully qeued %s'] +]; diff --git a/src/logger/codesWarn.ts b/src/logger/codesWarn.ts new file mode 100644 index 00000000..2649bc2c --- /dev/null +++ b/src/logger/codesWarn.ts @@ -0,0 +1,28 @@ +import { WARN_0, WARN_1, WARN_2, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_12, WARN_13, WARN_14, WARN_15, WARN_17, WARN_18, WARN_19, WARN_20, WARN_21, WARN_22, WARN_23, WARN_24, WARN_25 } from './codesConstants'; + +export const codesWarn: [number, string][] = [ + [WARN_0, 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'], + [WARN_1, 'splitio-engine:value => Defined attribute [%s], no attributes received.'], + [WARN_2, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], + [WARN_4, 'splitio-sync:my-segments => Retrying download of segments #%s. Reason: %s'], + [WARN_5, 'splitio-sync:split-changes => Error while doing fetch of Splits. %s'], + [WARN_6, 'splitio-sync:sse-handler => Error parsing SSE error notification: %s'], + [WARN_7, 'splitio-sync:sse-handler => Error parsing new SSE message notification: %s'], + [WARN_8, 'splitio-sync:push-manager => %sFalling back to polling mode.'], + [WARN_9, 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'], + [WARN_10, 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'], + [WARN_11, 'splitio-client:event-tracker => Failed to queue %s'], + [WARN_12, '%s: Property %s is of invalid type. Setting value to null.'], + [WARN_13, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], + [WARN_14, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], + [WARN_15, '%s: %s "%s" is not of type string, converting.'], + [WARN_17, '%s: %s "%s" has extra whitespace, trimming.'], + [WARN_18, '%s: you passed "%s" that does not exist in this environment, please double check what Splits exist in the web console.'], + [WARN_19, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], + [WARN_20, '%s: Traffic Type %s does not have any corresponding Splits in this environment, make sure you\'re tracking your events to a valid traffic type defined in the Split console.'], + [WARN_21, 'splitio-settings => %s integration %s at settings %s invalid. %s'], + [WARN_22, 'Factory instantiation: split filters have been configured but will have no effect if mode is not \'%s\', since synchronization is being deferred to an external tool.'], + [WARN_23, 'Factory instantiation: split filter at position \'%s\' is invalid. It must be an object with a valid filter type (\'byName\' or \'byPrefix\') and a list of \'values\'.'], + [WARN_24, 'Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'], + [WARN_25, 'splitio-settings => The provided storage is invalid. Fallbacking into default MEMORY storage'] +]; diff --git a/src/logger/codesWarnNode.ts b/src/logger/codesWarnNode.ts new file mode 100644 index 00000000..04288410 --- /dev/null +++ b/src/logger/codesWarnNode.ts @@ -0,0 +1,5 @@ +import { WARN_3 } from './codesConstantsNode'; + +export const codesWarnNode: [number, string][] = [ + [WARN_3, 'splitio-offline:splits-fetcher => .split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'], +]; diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 2bb3c7b1..70dbc4fe 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -1,6 +1,7 @@ import { LogLevels, isLogLevelString } from './index'; import { ILoggerAPI } from '../types'; import { ILogger } from './types'; +import { ERROR_2 } from './codesConstants'; // const log = logFactory('splitio-utils:logger'); @@ -15,7 +16,7 @@ export function createLoggerAPI(log: ILogger): ILoggerAPI { if (isLogLevelString(logLevel)) { log.setLogLevel(logLevel); } else { - log.error('Invalid Log Level - No changes to the logs will be applied.'); + log.error(ERROR_2); } } diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index 486c4822..c5370451 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -5,6 +5,7 @@ import { ISdkReadinessManager } from './types'; import { IEventEmitter } from '../types'; import { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from './constants'; import { ILogger } from '../logger/types'; +import { ERROR_3, INFO_0, INFO_1, WARN_2 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory(''); @@ -36,7 +37,7 @@ export default function sdkReadinessManagerFactory( readinessManager.gate.on(NEW_LISTENER_EVENT, (event: any) => { if (event === SDK_READY || event === SDK_READY_TIMED_OUT) { if (readinessManager.isReady()) { - log.error(`A listener was added for ${event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT'} on the SDK, which has already fired and won't be emitted again. The callback won't be executed.`); + log.error(ERROR_3, [event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT']); } else if (event === SDK_READY) { readyCbCount++; } @@ -47,7 +48,7 @@ export default function sdkReadinessManagerFactory( const readyPromise = generateReadyPromise(); readinessManager.gate.once(SDK_READY_FROM_CACHE, () => { - log.info('Split SDK is ready from cache.'); + log.info(INFO_0); }); // default onRejected handler, that just logs the error, if ready promise doesn't have one. @@ -58,9 +59,9 @@ export default function sdkReadinessManagerFactory( function generateReadyPromise() { const promise = promiseWrapper(new Promise((resolve, reject) => { readinessManager.gate.once(SDK_READY, () => { - log.info('Split SDK is ready.'); + log.info(INFO_1); - if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn('No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'); + if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn(WARN_2); resolve(); }); readinessManager.gate.once(SDK_READY_TIMED_OUT, reject); diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index e34d682e..4750d154 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -8,6 +8,7 @@ import { CONTROL } from '../utils/constants'; import { IClientFactoryParams } from './types'; import { IEvaluationResult } from '../evaluator/types'; import { SplitIO, ImpressionDTO } from '../types'; +import { INFO_2, INFO_3 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client'); @@ -76,10 +77,10 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl } const { treatment, label, changeNumber, config = null } = evaluation; - log.info(`Split: ${splitName}. Key: ${matchingKey}. Evaluation: ${treatment}. Label: ${label}`); + log.info(INFO_2, [splitName, matchingKey, treatment, label]); if (validateSplitExistance(log, readinessManager, splitName, label, invokingMethodName)) { - log.info('Queueing corresponding impression.'); + log.info(INFO_3); queue.push({ feature: splitName, keyName: matchingKey, diff --git a/src/sdkClient/sdkClientMethod.ts b/src/sdkClient/sdkClientMethod.ts index 4bb1d7ef..5e5574c2 100644 --- a/src/sdkClient/sdkClientMethod.ts +++ b/src/sdkClient/sdkClientMethod.ts @@ -1,6 +1,7 @@ import { ISdkClientFactoryParams } from './types'; import { SplitIO } from '../types'; import { sdkClientFactory } from './sdkClient'; +import { DEBUG_31 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); @@ -16,7 +17,7 @@ export function sdkClientMethodFactory(params: ISdkClientFactoryParams): () => S throw new Error('Shared Client not supported by the storage mechanism. Create isolated instances instead.'); } - log.debug('Retrieving SDK client.'); + log.debug(DEBUG_31); return clientInstance; }; } diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index 97408161..17109d02 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -7,6 +7,7 @@ import { sdkClientFactory } from './sdkClient'; import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; +import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); @@ -41,7 +42,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? return function client(key?: SplitIO.SplitKey) { if (key === undefined) { - log.debug('Retrieving default SDK client.'); + log.debug(DEBUG_32); return mainClientInstance; } @@ -75,9 +76,9 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? sharedSyncManager.start(); - log.info('New shared client instance created.'); + log.info(INFO_4); } else { - log.debug('Retrieving existing SDK client.'); + log.debug(DEBUG_33); } return clientInstances[instanceId]; diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index 8d103cf6..23fd408c 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -8,6 +8,7 @@ import { sdkClientFactory } from './sdkClient'; import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; +import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); @@ -48,7 +49,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? return function client(key?: SplitIO.SplitKey, trafficType?: string) { if (key === undefined) { - log.debug('Retrieving default SDK client.'); + log.debug(DEBUG_32); return mainClientInstance; } @@ -90,9 +91,9 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? sharedSyncManager.start(); - log.info('New shared client instance created.'); + log.info(INFO_4); } else { - log.debug('Retrieving existing SDK client.'); + log.debug(DEBUG_33); } return clientInstances[instanceId]; diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index f98c40fa..dc2adef7 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -10,6 +10,7 @@ import { getMatching } from '../utils/key'; import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; import { createLoggerAPI } from '../logger/sdkLogger'; +import { INFO_5, INFO_6, ERROR_4 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); @@ -79,7 +80,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. syncManager && syncManager.start(); signalListener && signalListener.start(); - log.info('New Split SDK instance created.'); + log.info(INFO_5); return { // Split evaluation and event tracking engine @@ -88,8 +89,8 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // Manager API to explore available information // @ts-ignore manager() { - if (managerInstance) log.info('Manager instance retrieved.'); - else log.error('Manager instance is not available. Provide the manager module on settings.'); + if (managerInstance) log.info(INFO_6); + else log.error(ERROR_4); return managerInstance; }, diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index dcce01f7..5dc2d5e3 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -3,6 +3,7 @@ import { SplitError, SplitNetworkError } from '../utils/lang/errors'; import objectAssign from 'object-assign'; import { IMetadata } from '../dtos/types'; import { ILogger } from '../logger/types'; +import { ERROR_39, ERROR_5 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-services:service'); @@ -22,7 +23,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I const fetch = getFetch && getFetch(); // if fetch is not available, log Error - if (!fetch) log.error(`${messageNoFetch} The SDK will not get ready.`); + if (!fetch) log.error(ERROR_5, [messageNoFetch]); const headers: Record = { 'Accept': 'application/json', @@ -67,7 +68,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I } if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else. - log[logErrorsAsInfo ? 'info' : 'error'](`Response status is not OK. Status: ${resp ? resp.status : 'NO_STATUS'}. URL: ${url}. Message: ${msg}`); + log[logErrorsAsInfo ? 'info' : 'error'](ERROR_39, [resp ? resp.status : 'NO_STATUS', url, msg]); } // passes `undefined` as statusCode if not an HTTP error (resp === undefined) diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index a94eb997..e35c8a91 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -9,6 +9,7 @@ import parseCondition, { IMockSplitEntry } from './parseCondition'; import { ISplitPartial } from '../../../dtos/types'; import { SplitIO } from '../../../types'; import { ILogger } from '../../../logger/types'; +import { DEBUG_34, DEBUG_35, ERROR_6, WARN_3 } from '../../../logger/codesConstantsNode'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-offline:splits-fetcher'); @@ -60,12 +61,12 @@ function readSplitConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFileP let tuple: string | string[] = line.trim(); if (tuple === '' || tuple.charAt(0) === '#') { - log.debug(`Ignoring empty line or comment at #${index}`); + log.debug(DEBUG_34, [index]); } else { tuple = tuple.split(/\s+/); if (tuple.length !== 2) { - log.debug(`Ignoring line since it does not have exactly two columns #${index}`); + log.debug(DEBUG_35, [index]); } else { const splitName = tuple[SPLIT_POSITION]; const condition = parseCondition({ treatment: tuple[TREATMENT_POSITION] }); @@ -102,7 +103,7 @@ function readYAMLConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFilePa const splitName = Object.keys(splitEntry)[0]; if (!splitName || !isString(splitEntry[splitName].treatment)) - log.error('Ignoring entry on YAML since the format is incorrect.'); + log.error(ERROR_6); const mockData = splitEntry[splitName]; @@ -167,7 +168,7 @@ export default function splitsParserFromFile({ features, log }: { features?: Spl // If we have a filePath, it means the extension is correct, choose the parser. if (endsWith(filePath, '.split')) { - log.warn('.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'); + log.warn(WARN_3); mockData = readSplitConfigFile(log, filePath); } else { mockData = readYAMLConfigFile(log, filePath); diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index cb8738db..f9a2aa5d 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -8,6 +8,7 @@ import { ISyncTask } from '../../types'; import { ISettings } from '../../../types'; import { CONTROL } from '../../../utils/constants'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; +import { DEBUG_36, ERROR_7 } from '../../../logger/codesConstants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-producer:offline'); @@ -31,11 +32,11 @@ export function fromObjectUpdaterFactory( splitsMock = splitsParser(settings); } catch (err) { loadError = err; - log.error(`There was an issue loading the mock Splits data, no changes will be applied to the current cache. ${err}`); + log.error(ERROR_7, [err]); } if (!loadError && splitsMock) { - log.debug('Splits data: '); + log.debug(DEBUG_36); log.debug(JSON.stringify(splitsMock)); forOwn(splitsMock, function (val, name) { diff --git a/src/sync/polling/pollingManagerCS.ts b/src/sync/polling/pollingManagerCS.ts index daaef660..9ef21908 100644 --- a/src/sync/polling/pollingManagerCS.ts +++ b/src/sync/polling/pollingManagerCS.ts @@ -8,6 +8,7 @@ import splitsSyncTaskFactory from './syncTasks/splitsSyncTask'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants'; +import { INFO_7, INFO_8, INFO_9 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:polling-manager'); @@ -49,7 +50,7 @@ export default function pollingManagerCSFactory( if (!splitsSyncTask.isRunning()) return; // noop if not doing polling const splitsHaveSegments = storage.splits.usesSegments(); if (splitsHaveSegments !== mySegmentsSyncTask.isRunning()) { - log.info(`Turning segments data polling ${splitsHaveSegments ? 'ON' : 'OFF'}.`); + log.info(INFO_7, [splitsHaveSegments ? 'ON' : 'OFF']); if (splitsHaveSegments) { startMySegmentsSyncTasks(); } else { @@ -78,7 +79,7 @@ export default function pollingManagerCSFactory( // Start periodic fetching (polling) start() { - log.info('Starting polling'); + log.info(INFO_8); splitsSyncTask.start(); if (storage.splits.usesSegments()) startMySegmentsSyncTasks(); @@ -86,7 +87,7 @@ export default function pollingManagerCSFactory( // Stop periodic fetching (polling) stop() { - log.info('Stopping polling'); + log.info(INFO_9); if (splitsSyncTask.isRunning()) splitsSyncTask.stop(); stopMySegmentsSyncTasks(); diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index ee4ddcf2..e0750bb3 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -6,6 +6,8 @@ import { ISplitApi } from '../../services/types'; import { ISettings } from '../../types'; import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types'; import thenable from '../../utils/promise/thenable'; +import { INFO_8, INFO_9 } from '../../logger/codesConstants'; +import { DEBUG_37, DEBUG_38 } from '../../logger/codesConstantsNode'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:polling-manager'); @@ -30,9 +32,9 @@ export default function pollingManagerSSFactory( // Start periodic fetching (polling) start() { - log.info('Starting polling'); - log.debug(`Splits will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`); - log.debug(`Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`); + log.info(INFO_8); + log.debug(DEBUG_37, [settings.scheduler.featuresRefreshRate]); // @TODO remove since we already log it in syncTask debug log? + log.debug(DEBUG_38, [settings.scheduler.segmentsRefreshRate]); // @TODO remove since we already log it in syncTask debug log? const startingUp = splitsSyncTask.start(); if (thenable(startingUp)) { @@ -44,7 +46,7 @@ export default function pollingManagerSSFactory( // Stop periodic fetching (polling) stop() { - log.info('Stopping polling'); + log.info(INFO_9); if (splitsSyncTask.isRunning()) splitsSyncTask.stop(); if (segmentsSyncTask.isRunning()) segmentsSyncTask.stop(); diff --git a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts index a47787c6..108541a9 100644 --- a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts @@ -10,6 +10,7 @@ import mySegmentsFetcherFactory from '../fetchers/mySegmentsFetcher'; import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; +import { WARN_4 } from '../../../logger/codesConstants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:my-segments'); @@ -75,7 +76,7 @@ function mySegmentsUpdaterFactory( if (startingUp && retriesOnFailureBeforeReady > retry) { retry += 1; - log.warn(`Retrying download of segments #${retry}. Reason: ${error}`); + log.warn(WARN_4, [retry, error]); return _mySegmentsUpdater(retry); // no need to forward `segmentList` and `noCache` params } else { startingUp = false; diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index b22c605f..74dc7378 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -11,6 +11,7 @@ import { IFetchSegmentChanges } from '../../../services/types'; import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; +import { DEBUG_41, DEBUG_40, DEBUG_39, ERROR_8 } from '../../../logger/codesConstantsNode'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:segment-changes'); @@ -49,7 +50,7 @@ function segmentChangesUpdaterFactory( * This param is used by SplitUpdateWorker on server-side SDK, to fetch new registered segments on SPLIT_UPDATE notifications. */ return function segmentChangesUpdater(segmentNames?: string[], noCache?: boolean, fetchOnlyNew?: boolean) { - log.debug('Started segments update'); + log.debug(DEBUG_41); // If not a segment name provided, read list of available segments names to be updated. let segments = segmentNames ? segmentNames : segmentsCache.getRegisteredSegments(); @@ -62,7 +63,7 @@ function segmentChangesUpdaterFactory( const segmentName = segments[index]; const since = segmentsCache.getChangeNumber(segmentName); - log.debug(`Processing segment ${segmentName}`); + log.debug(DEBUG_40, [segmentName]); updaters.push(segmentChangesFetcher(since, segmentName, noCache, _promiseDecorator).then(function (changes) { let changeNumber = -1; @@ -74,7 +75,7 @@ function segmentChangesUpdaterFactory( changeNumber = x.till; } - log.debug(`Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`); + log.debug(DEBUG_39, [segmentName, x.till, x.added.length, x.removed.length]); }); return changeNumber; @@ -98,7 +99,7 @@ function segmentChangesUpdaterFactory( if (error.statusCode === 403) { // @TODO although factory status is destroyed, synchronization is not stopped readiness.destroy(); - log.error('Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'); + log.error(ERROR_8); } return false; diff --git a/src/sync/polling/syncTasks/splitsSyncTask.ts b/src/sync/polling/syncTasks/splitsSyncTask.ts index 3bea3172..0eac3147 100644 --- a/src/sync/polling/syncTasks/splitsSyncTask.ts +++ b/src/sync/polling/syncTasks/splitsSyncTask.ts @@ -13,6 +13,7 @@ import thenable from '../../../utils/promise/thenable'; import { ISettings } from '../../../types'; import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; +import { DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, WARN_5, INFO_10 } from '../../../logger/codesConstants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:split-changes'); @@ -117,7 +118,7 @@ export function splitChangesUpdaterFactory( * @param {number} retry current number of retry attemps */ function _splitChangesUpdater(since: number, retry = 0): Promise { - log.debug(`Spin up split update using since = ${since}`); + log.debug(DEBUG_42, [since]); const fetcherPromise = splitChangesFetcher(since, noCache, _promiseDecorator) .then((splitChanges: ISplitChangesResponse) => { @@ -125,9 +126,9 @@ export function splitChangesUpdaterFactory( const mutation = computeSplitsMutation(splitChanges.splits); - log.debug(`New splits ${mutation.added.length}`); - log.debug(`Removed splits ${mutation.removed.length}`); - log.debug(`Segment names collected ${mutation.segments.length}`); + log.debug(DEBUG_43, [mutation.added.length]); + log.debug(DEBUG_44, [mutation.removed.length]); + log.debug(DEBUG_45, [mutation.segments.length]); // Write into storage // @TODO if allowing custom storages, wrap errors as SplitErrors to distinguish from user callback errors @@ -153,11 +154,11 @@ export function splitChangesUpdaterFactory( startingUp = false; // Stop retrying. } - log.warn(`Error while doing fetch of Splits. ${error}`); + log.warn(WARN_5, [error]); if (startingUp && retriesOnFailureBeforeReady > retry) { retry += 1; - log.info(`Retrying download of splits #${retry}. Reason: ${error}`); + log.info(INFO_10, [retry, error]); return _splitChangesUpdater(since, retry); } else { startingUp = false; diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index 5392d7ba..eafc9d5f 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -5,6 +5,7 @@ import { IPushEventEmitter } from '../types'; import { ISseEventHandler } from '../SSEClient/types'; import { INotificationError } from './types'; import { ILogger } from '../../../logger/types'; +import { WARN_6, ERROR_9, WARN_7, DEBUG_46 } from '../../../logger/codesConstants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:sse-handler'); @@ -41,11 +42,11 @@ export default function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventE try { errorWithParsedData = errorParser(error); } catch (err) { - log.warn(`Error parsing SSE error notification: ${err}`); + log.warn(WARN_6, [err]); } let errorMessage = errorWithParsedData.parsedData && errorWithParsedData.parsedData.message; - log.error(`Fail to connect to streaming, with error message: ${errorMessage}`); + log.error(ERROR_9, [errorMessage]); if (isRetryableError(errorWithParsedData)) { pushEmitter.emit(PUSH_RETRYABLE_ERROR); @@ -60,12 +61,12 @@ export default function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventE try { messageWithParsedData = messageParser(message); } catch (err) { - log.warn(`Error parsing new SSE message notification: ${err}`); + log.warn(WARN_7, [err]); return; } const { parsedData, data, channel, timestamp } = messageWithParsedData; - log.debug(`New SSE message received, with data: ${data}.`); + log.debug(DEBUG_46, [data]); // we only handle update events if streaming is up. if (!notificationKeeper.isStreamingUp() && parsedData.type !== OCCUPANCY && parsedData.type !== CONTROL) diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index f97aa53b..accdb7f4 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -18,6 +18,7 @@ import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { MY_SEGMENTS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP } from './constants'; import { IPlatform } from '../../sdkFactory/types'; +import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:push-manager'); @@ -41,7 +42,7 @@ export default function pushManagerFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(`${e}Falling back to polling mode.`); + log.warn(WARN_8, [e]); return; } const authenticate = authenticateFactory(fetchAuth); @@ -89,14 +90,14 @@ export default function pushManagerFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.info(INFO_11, [delayInSeconds]); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info('Connecting to push streaming.'); + log.info(INFO_13); const userKeys = userKey ? Object.keys(workers) : undefined; authenticate(userKeys).then( @@ -106,7 +107,7 @@ export default function pushManagerFactory( // 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to // close the sseClient in case the org has been bloqued while the instance was connected to streaming if (!authData.pushEnabled) { - log.info('Streaming is not available. Switching to polling mode.'); + log.info(INFO_14); pushEmitter.emit(PUSH_NONRETRYABLE_ERROR); return; } @@ -123,7 +124,7 @@ export default function pushManagerFactory( function (error) { if (disconnected) return; - log.error(`Failed to authenticate for streaming. Error: "${error.message}".`); + log.error(ERROR_10, [error.message]); // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { @@ -140,7 +141,7 @@ export default function pushManagerFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info('Disconnecting from push streaming.'); + log.info(INFO_15); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -178,7 +179,7 @@ export default function pushManagerFactory( // retry streaming reconnect with backoff algorithm let delayInMillis = connectPushRetryBackoff.scheduleCall(); - log.info(`Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.info(INFO_12, [delayInMillis / 1000]); pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index ebbd97c0..2a19ccce 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -17,6 +17,7 @@ import { IFetchAuth } from '../../services/types'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { IPlatform } from '../../sdkFactory/types'; +import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:push-manager'); @@ -39,7 +40,7 @@ export default function pushManagerCSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(`${e}Falling back to polling mode.`); + log.warn(WARN_8, [e]); return; } const authenticate = authenticateFactory(fetchAuth); @@ -85,14 +86,14 @@ export default function pushManagerCSFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.info(INFO_11, [delayInSeconds]); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info('Connecting to push streaming.'); + log.info(INFO_13); const userKeys = Object.keys(workers); // [Only for client-side] authenticate(userKeys).then( @@ -102,7 +103,7 @@ export default function pushManagerCSFactory( // 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to // close the sseClient in case the org has been bloqued while the instance was connected to streaming if (!authData.pushEnabled) { - log.info('Streaming is not available. Switching to polling mode.'); + log.info(INFO_14); pushEmitter.emit(PUSH_NONRETRYABLE_ERROR); return; } @@ -119,7 +120,7 @@ export default function pushManagerCSFactory( function (error) { if (disconnected) return; - log.error(`Failed to authenticate for streaming. Error: "${error.message}".`); + log.error(ERROR_10, [error.message]); // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { @@ -136,7 +137,7 @@ export default function pushManagerCSFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info('Disconnecting from push streaming.'); + log.info(INFO_15); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -173,7 +174,7 @@ export default function pushManagerCSFactory( // retry streaming reconnect with backoff algorithm let delayInMillis = connectPushRetryBackoff.scheduleCall(); - log.info(`Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.info(INFO_12, [delayInMillis / 1000]); pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index c9f47f11..ca8e2649 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -14,6 +14,7 @@ import { authenticateFactory } from './AuthClient'; import SSEClient from './SSEClient'; import { ISettings } from '../../types'; import { IPlatform } from '../../sdkFactory/types'; +import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:push-manager'); @@ -35,7 +36,7 @@ export default function pushManagerSSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(`${e}Falling back to polling mode.`); + log.warn(WARN_8, [e]); return; } const authenticate = authenticateFactory(fetchAuth); @@ -66,14 +67,14 @@ export default function pushManagerSSFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(`Refreshing streaming token in ${delayInSeconds} seconds.`); + log.info(INFO_11, [delayInSeconds]); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info('Connecting to push streaming.'); + log.info(INFO_13); authenticate().then( function (authData) { @@ -82,7 +83,7 @@ export default function pushManagerSSFactory( // 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to // close the sseClient in case the org has been bloqued while the instance was connected to streaming if (!authData.pushEnabled) { - log.info('Streaming is not available. Switching to polling mode.'); + log.info(INFO_14); pushEmitter.emit(PUSH_NONRETRYABLE_ERROR); return; } @@ -96,7 +97,7 @@ export default function pushManagerSSFactory( function (error) { if (disconnected) return; - log.error(`Failed to authenticate for streaming. Error: "${error.message}".`); + log.error(ERROR_10, [error.message]); // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { @@ -113,7 +114,7 @@ export default function pushManagerSSFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info('Disconnecting from push streaming.'); + log.info(INFO_15); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -150,7 +151,7 @@ export default function pushManagerSSFactory( // retry streaming reconnect with backoff algorithm let delayInMillis = connectPushRetryBackoff.scheduleCall(); - log.info(`Attempting to reconnect in ${delayInMillis / 1000} seconds.`); + log.info(INFO_12, [delayInMillis / 1000]); pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already }); diff --git a/src/sync/submitters/eventsSyncTask.ts b/src/sync/submitters/eventsSyncTask.ts index 19859240..4895f14a 100644 --- a/src/sync/submitters/eventsSyncTask.ts +++ b/src/sync/submitters/eventsSyncTask.ts @@ -3,6 +3,7 @@ import { IPostEventsBulk } from '../../services/types'; import { ISyncTask, ITimeTracker } from '../types'; import { submitterSyncTaskFactory } from './submitterSyncTask'; import { ILogger } from '../../logger/types'; +import { INFO_16 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:submitters'); @@ -37,7 +38,7 @@ export function eventsSyncTaskFactory( // register eventsSubmitter to be executed when events cache is full eventsCache.setOnFullQueueCb(() => { - log.info('Flushing full events queue and reseting timer.'); + log.info(INFO_16); syncTask.execute(); }); diff --git a/src/sync/submitters/submitterSyncTask.ts b/src/sync/submitters/submitterSyncTask.ts index 4fc01e08..02fdfc4e 100644 --- a/src/sync/submitters/submitterSyncTask.ts +++ b/src/sync/submitters/submitterSyncTask.ts @@ -2,6 +2,7 @@ import syncTaskFactory from '../syncTask'; import { ISyncTask, ITimeTracker } from '../types'; import { IRecorderCacheConsumerSync } from '../../storages/types'; import { ILogger } from '../../logger/types'; +import { INFO_17, WARN_9, WARN_10 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:submitters'); @@ -27,7 +28,7 @@ export function submitterSyncTaskFactory( const data = sourceCache.state(); const dataCount: number | '' = typeof data.length === 'number' ? data.length : ''; - log.info(`Pushing ${dataCount} ${dataName}.`); + log.info(INFO_17, [dataCount, dataName]); const latencyTrackerStop = latencyTracker && latencyTracker.start(); const jsonPayload = JSON.stringify(fromCacheToPayload ? fromCacheToPayload(data) : data); @@ -38,14 +39,14 @@ export function submitterSyncTaskFactory( sourceCache.clear(); // we clear the queue if request successes. }).catch(err => { if (!maxRetries) { - log.warn(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); + log.warn(WARN_9, [dataCount, dataName, err]); } else if (retries === maxRetries) { retries = 0; sourceCache.clear(); // we clear the queue if request fails after retries. - log.warn(`Droping ${dataCount} ${dataName} after retry. Reason ${err}.`); + log.warn(WARN_9, [dataCount, dataName, err]); } else { retries++; - log.warn(`Failed to push ${dataCount} ${dataName}, keeping data to retry on next iteration. Reason ${err}.`); + log.warn(WARN_10, [dataCount, dataName, err]); } }); diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index 6ef0c675..e5dee1eb 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -8,6 +8,7 @@ import { IStorageSync } from '../storages/types'; import { IPushManagerFactoryParams, IPushManager, IPushManagerCS } from './streaming/types'; import { IPollingManager, IPollingManagerCS, IPollingManagerFactoryParams } from './polling/types'; import { PUSH_SUBSYSTEM_UP, PUSH_SUBSYSTEM_DOWN } from './streaming/constants'; +import { INFO_18, INFO_19, INFO_20 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // export const log = logFactory('splitio-sync:sync-manager'); @@ -60,15 +61,15 @@ export function syncManagerOnlineFactory( function startPolling() { if (!pollingManager.isRunning()) { - log.info('Streaming not available. Starting periodic fetch of data.'); + log.info(INFO_18); pollingManager.start(); } else { - log.info('Streaming couldn\'t connect. Continue periodic fetch of data.'); + log.info(INFO_19); } } function stopPollingAndSyncAll() { - log.info('PUSH (re)connected. Syncing and stopping periodic fetch of data.'); + log.info(INFO_20); // if polling, stop if (pollingManager.isRunning()) pollingManager.stop(); diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index ed0c16e9..c064930e 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -1,3 +1,4 @@ +import { DEBUG_48, DEBUG_47, DEBUG_49 } from '../logger/codesConstants'; import { ILogger } from '../logger/types'; import { ISyncTask } from './types'; // import { logFactory } from '../logger/sdkLogger'; @@ -17,7 +18,7 @@ export default function syncTaskFactory(log: ILogge function execute(...args: Input) { executing = true; - log.debug(`Running ${taskName}`); + log.debug(DEBUG_48, [taskName]); return task(...args).then(result => { executing = false; if (running) timeoutID = setTimeout(execute, period, ...args); @@ -35,7 +36,7 @@ export default function syncTaskFactory(log: ILogge start(...args: Input) { if (!running) { running = true; - log.debug(`Starting ${taskName}. Running each ${period} millis`); + log.debug(DEBUG_47, [taskName, period]); return execute(...args); } }, @@ -43,7 +44,7 @@ export default function syncTaskFactory(log: ILogge stop() { running = false; if (timeoutID) { - log.debug(`Stopping ${taskName}`); + log.debug(DEBUG_49, [taskName]); clearTimeout(timeoutID); timeoutID = undefined; } diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index 9e200705..4397ea68 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -4,6 +4,7 @@ import { IEventsCacheBase } from '../storages/types'; import { IEventsHandler, IEventTracker } from './types'; import { SplitIO } from '../types'; import { ILogger } from '../logger/types'; +import { INFO_21, WARN_11 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client:event-tracker'); @@ -25,7 +26,7 @@ export default function eventTrackerFactory( const msg = `event of type "${eventTypeId}" for traffic type "${trafficTypeName}". Key: ${key}. Value: ${value}. Timestamp: ${timestamp}. ${properties ? 'With properties.' : 'With no properties.'}`; if (tracked) { - log.info(`Successfully qeued ${msg}`); + log.info(INFO_21, [msg]); if (integrationsManager) { // Wrap in a timeout because we don't want it to be blocking. setTimeout(function () { @@ -37,7 +38,7 @@ export default function eventTrackerFactory( }, 0); } } else { - log.warn(`Failed to queue ${msg}`); + log.warn(WARN_11, [msg]); } return tracked; diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index d5144065..217c947b 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -7,6 +7,7 @@ import { IMetadata } from '../dtos/types'; import { SplitIO, ImpressionDTO } from '../types'; import { IImpressionObserver } from './impressionObserver/types'; import { ILogger } from '../logger/types'; +import { DEBUG_50, ERROR_11, ERROR_12 } from '../logger/codesConstants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client:impressions-tracker'); @@ -64,9 +65,9 @@ export default function impressionsTrackerFactory( // If we're on an async storage, handle error and log it. if (thenable(res)) { res.then(() => { - log.debug(`Successfully stored ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}.`); + log.debug(DEBUG_50, [impressionsCount, impressionsCount === 1 ? '' : 's']); }).catch(err => { - log.error(`Could not store impressions bulk with ${impressionsCount} impression${impressionsCount === 1 ? '' : 's'}. Error: ${err}`); + log.error(ERROR_11, [impressionsCount, impressionsCount === 1 ? '' : 's', err]); }); } @@ -90,7 +91,7 @@ export default function impressionsTrackerFactory( try { // An exception on the listeners should not break the SDK. if (impressionListener) impressionListener.logImpression(impressionData); } catch (err) { - log.error(`Impression listener logImpression method threw: ${err}.`); + log.error(ERROR_12, [err]); } }, 0); } diff --git a/src/utils/inputValidation/attributes.ts b/src/utils/inputValidation/attributes.ts index 0a938c64..005a14e0 100644 --- a/src/utils/inputValidation/attributes.ts +++ b/src/utils/inputValidation/attributes.ts @@ -1,6 +1,7 @@ import { isObject } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; +import { ERROR_13 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); @@ -9,6 +10,6 @@ export function validateAttributes(log: ILogger, maybeAttrs: any, method: string if (isObject(maybeAttrs) || maybeAttrs == undefined) // eslint-disable-line eqeqeq return maybeAttrs; - log.error(`${method}: attributes must be a plain object.`); + log.error(ERROR_13, [method]); return false; } diff --git a/src/utils/inputValidation/event.ts b/src/utils/inputValidation/event.ts index 716661a3..e8e6e7ad 100644 --- a/src/utils/inputValidation/event.ts +++ b/src/utils/inputValidation/event.ts @@ -1,3 +1,4 @@ +import { ERROR_14, ERROR_15, ERROR_16, ERROR_17 } from '../../logger/codesConstants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; @@ -7,14 +8,14 @@ const EVENT_TYPE_REGEX = /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/; export function validateEvent(log: ILogger, maybeEvent: any, method: string): string | false { if (maybeEvent == undefined) { // eslint-disable-line eqeqeq - log.error(`${method}: you passed a null or undefined event_type, event_type must be a non-empty string.`); + log.error(ERROR_15, [method]); } else if (!isString(maybeEvent)) { - log.error(`${method}: you passed an invalid event_type, event_type must be a non-empty string.`); + log.error(ERROR_16, [method]); } else { // It is a string. if (maybeEvent.length === 0) { - log.error(`${method}: you passed an empty event_type, event_type must be a non-empty string.`); + log.error(ERROR_17, [method]); } else if (!EVENT_TYPE_REGEX.test(maybeEvent)) { - log.error(`${method}: you passed "${maybeEvent}", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.`); + log.error(ERROR_14, [method, maybeEvent]); } else { return maybeEvent; } diff --git a/src/utils/inputValidation/eventProperties.ts b/src/utils/inputValidation/eventProperties.ts index 7a1e4e57..15912cc8 100644 --- a/src/utils/inputValidation/eventProperties.ts +++ b/src/utils/inputValidation/eventProperties.ts @@ -1,6 +1,7 @@ import { isObject, shallowClone, isString, isFiniteNumber, isBoolean } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; +import { ERROR_18, ERROR_19, WARN_12, WARN_13 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); @@ -18,7 +19,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth if (maybeProperties == undefined) return { properties: null, size: BASE_EVENT_SIZE }; // eslint-disable-line eqeqeq if (!isObject(maybeProperties)) { - log.error(`${method}: properties must be a plain object.`); + log.error(ERROR_18, [method]); return { properties: false, size: BASE_EVENT_SIZE }; } @@ -31,7 +32,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth }; if (keys.length > MAX_PROPERTIES_AMOUNT) { - log.warn(`${method}: Event has more than 300 properties. Some of them will be trimmed when processed.`); + log.warn(WARN_13, [method]); } for (let i = 0; i < keys.length; i++) { @@ -48,7 +49,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth clone[keys[i]] = null; val = null; isNullVal = true; - log.warn(`${method}: Property ${keys[i]} is of invalid type. Setting value to null.`); + log.warn(WARN_12, [method, keys[i]]); } if (isNullVal) output.size += ECMA_SIZES.NULL; @@ -57,7 +58,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth else if (isStringVal) output.size += val.length * ECMA_SIZES.STRING; if (output.size > MAX_PROPERTIES_SIZE) { - log.error(`${method}: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.`); + log.error(ERROR_19, [method]); output.properties = false; break; } diff --git a/src/utils/inputValidation/eventValue.ts b/src/utils/inputValidation/eventValue.ts index 5b3387da..3653ecd3 100644 --- a/src/utils/inputValidation/eventValue.ts +++ b/src/utils/inputValidation/eventValue.ts @@ -1,3 +1,4 @@ +import { ERROR_20 } from '../../logger/codesConstants'; import { ILogger } from '../../logger/types'; import { isFiniteNumber } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; @@ -7,6 +8,6 @@ export function validateEventValue(log: ILogger, maybeValue: any, method: string if (isFiniteNumber(maybeValue) || maybeValue == undefined) // eslint-disable-line eqeqeq return maybeValue; - log.error(`${method}: value must be a finite number.`); + log.error(ERROR_20, [method]); return false; } diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index 25e1b9dd..ebdfd80a 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -1,3 +1,4 @@ +import { ERROR_21, WARN_14 } from '../../logger/codesConstants'; import { ILogger } from '../../logger/types'; import { IReadinessManager } from '../../readiness/types'; // import { logFactory } from '../../logger/sdkLogger'; @@ -6,13 +7,13 @@ import { IReadinessManager } from '../../readiness/types'; export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadinessManager): boolean { if (!readinessManager.isDestroyed()) return true; - log.error('Client has already been destroyed - no calls possible.'); + log.error(ERROR_21); return false; } export function validateIfOperational(log: ILogger, readinessManager: IReadinessManager, method: string) { if (readinessManager.isReady() || readinessManager.isReadyFromCache()) return true; - log.warn(`${method}: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.`); + log.warn(WARN_14, [method]); return false; } diff --git a/src/utils/inputValidation/key.ts b/src/utils/inputValidation/key.ts index d37a0363..0473ac83 100644 --- a/src/utils/inputValidation/key.ts +++ b/src/utils/inputValidation/key.ts @@ -1,6 +1,7 @@ import { isObject, isString, isFiniteNumber, toString } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; +import { ERROR_22, WARN_15, ERROR_25, ERROR_23, ERROR_24, ERROR_26 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); @@ -8,11 +9,11 @@ const KEY_MAX_LENGTH = 250; function validateKeyValue(log: ILogger, maybeKey: any, method: string, type: string): string | false { if (maybeKey == undefined) { // eslint-disable-line eqeqeq - log.error(`${method}: you passed a null or undefined ${type}, ${type} must be a non-empty string.`); + log.error(ERROR_22, [method, type, type]); return false; } if (isFiniteNumber(maybeKey)) { - log.warn(`${method}: ${type} "${maybeKey}" is not of type string, converting.`); + log.warn(WARN_15, [method, type, maybeKey]); return toString(maybeKey); } if (isString(maybeKey)) { @@ -23,12 +24,12 @@ function validateKeyValue(log: ILogger, maybeKey: any, method: string, type: str if (maybeKey.length > 0 && maybeKey.length <= KEY_MAX_LENGTH) return maybeKey; if (maybeKey.length === 0) { - log.error(`${method}: you passed an empty string, ${type} must be a non-empty string.`); + log.error(ERROR_25, [method, type]); } else if (maybeKey.length > KEY_MAX_LENGTH) { - log.error(`${method}: ${type} too long, ${type} must be 250 characters or less.`); + log.error(ERROR_23, [method, type, type]); } } else { - log.error(`${method}: you passed an invalid ${type} type, ${type} must be a non-empty string.`); + log.error(ERROR_24, [method, type, type]); } return false; @@ -44,7 +45,7 @@ export function validateKey(log: ILogger, maybeKey: any, method: string): SplitI matchingKey, bucketingKey }; - log.error(`${method}: Key must be an object with bucketingKey and matchingKey with valid string properties.`); + log.error(ERROR_26, [method]); return false; } else { return validateKeyValue(log, maybeKey, method, 'key'); diff --git a/src/utils/inputValidation/split.ts b/src/utils/inputValidation/split.ts index aefa4323..8286c2da 100644 --- a/src/utils/inputValidation/split.ts +++ b/src/utils/inputValidation/split.ts @@ -1,3 +1,4 @@ +import { ERROR_22, ERROR_32, WARN_17, ERROR_33 } from '../../logger/codesConstants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; @@ -8,19 +9,19 @@ const TRIMMABLE_SPACES_REGEX = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/; export function validateSplit(log: ILogger, maybeSplit: any, method: string, item = 'split name'): string | false { if (maybeSplit == undefined) { // eslint-disable-line eqeqeq - log.error(`${method}: you passed a null or undefined ${item}, ${item} must be a non-empty string.`); + log.error(ERROR_22, [method, item, item]); } else if (!isString(maybeSplit)) { - log.error(`${method}: you passed an invalid ${item}, ${item} must be a non-empty string.`); + log.error(ERROR_32, [method, item, item]); } else { if (TRIMMABLE_SPACES_REGEX.test(maybeSplit)) { - log.warn(`${method}: ${item} "${maybeSplit}" has extra whitespace, trimming.`); + log.warn(WARN_17, [method, item, maybeSplit]); maybeSplit = maybeSplit.trim(); } if (maybeSplit.length > 0) { return maybeSplit; } else { - log.error(`${method}: you passed an empty ${item}, ${item} must be a non-empty string.`); + log.error(ERROR_33, [method, item, item]); } } diff --git a/src/utils/inputValidation/splitExistance.ts b/src/utils/inputValidation/splitExistance.ts index f3f3f3fc..c07f2194 100644 --- a/src/utils/inputValidation/splitExistance.ts +++ b/src/utils/inputValidation/splitExistance.ts @@ -1,6 +1,7 @@ import { SPLIT_NOT_FOUND } from '../labels'; import { IReadinessManager } from '../../readiness/types'; import { ILogger } from '../../logger/types'; +import { WARN_18 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); @@ -11,7 +12,7 @@ import { ILogger } from '../../logger/types'; export function validateSplitExistance(log: ILogger, readinessManager: IReadinessManager, splitName: string, labelOrSplitObj: any, method: string): boolean { if (readinessManager.isReady()) { // Only if it's ready we validate this, otherwise it may just be that the SDK is not ready yet. if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj == null) { - log.warn(`${method}: you passed "${splitName}" that does not exist in this environment, please double check what Splits exist in the web console.`); + log.warn(WARN_18, [method, splitName]); return false; } } diff --git a/src/utils/inputValidation/splits.ts b/src/utils/inputValidation/splits.ts index 2a333ee8..3e5fb52b 100644 --- a/src/utils/inputValidation/splits.ts +++ b/src/utils/inputValidation/splits.ts @@ -1,3 +1,4 @@ +import { ERROR_34 } from '../../logger/codesConstants'; import { ILogger } from '../../logger/types'; import { uniq } from '../lang'; import { validateSplit } from './split'; @@ -17,6 +18,6 @@ export function validateSplits(log: ILogger, maybeSplits: any, method: string, l if (validatedArray.length) return uniq(validatedArray); } - log.error(`${method}: ${listName} must be a non-empty array.`); + log.error(ERROR_34, [method, listName]); return false; } diff --git a/src/utils/inputValidation/trafficType.ts b/src/utils/inputValidation/trafficType.ts index d287f00c..3216925e 100644 --- a/src/utils/inputValidation/trafficType.ts +++ b/src/utils/inputValidation/trafficType.ts @@ -1,3 +1,4 @@ +import { ERROR_35, ERROR_36, ERROR_37, WARN_19 } from '../../logger/codesConstants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; @@ -7,15 +8,15 @@ const CAPITAL_LETTERS_REGEX = /[A-Z]/; export function validateTrafficType(log: ILogger, maybeTT: any, method: string): string | false { if (maybeTT == undefined) { // eslint-disable-line eqeqeq - log.error(`${method}: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.`); + log.error(ERROR_35, [method]); } else if (!isString(maybeTT)) { - log.error(`${method}: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.`); + log.error(ERROR_36, [method]); } else { if (maybeTT.length === 0) { - log.error(`${method}: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.`); + log.error(ERROR_37, [method]); } else { if (CAPITAL_LETTERS_REGEX.test(maybeTT)) { - log.warn(`${method}: traffic_type_name should be all lowercase - converting string to lowercase.`); + log.warn(WARN_19, [method]); maybeTT = maybeTT.toLowerCase(); } diff --git a/src/utils/inputValidation/trafficTypeExistance.ts b/src/utils/inputValidation/trafficTypeExistance.ts index 1fbc3601..7baafa20 100644 --- a/src/utils/inputValidation/trafficTypeExistance.ts +++ b/src/utils/inputValidation/trafficTypeExistance.ts @@ -5,11 +5,12 @@ import { IReadinessManager } from '../../readiness/types'; import { SDKMode } from '../../types'; import { MaybeThenable } from '../../dtos/types'; import { ILogger } from '../../logger/types'; +import { WARN_20 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); function logTTExistanceWarning(log: ILogger, maybeTT: string, method: string) { - log.warn(`${method}: Traffic Type ${maybeTT} does not have any corresponding Splits in this environment, make sure you're tracking your events to a valid traffic type defined in the Split console.`); + log.warn(WARN_20, [method, maybeTT]); } /** diff --git a/src/utils/settingsValidation/impressionsMode.ts b/src/utils/settingsValidation/impressionsMode.ts index 48c3bb65..68febe28 100644 --- a/src/utils/settingsValidation/impressionsMode.ts +++ b/src/utils/settingsValidation/impressionsMode.ts @@ -1,3 +1,4 @@ +import { ERROR_38 } from '../../logger/codesConstants'; import { ILogger } from '../../logger/types'; import { SplitIO } from '../../types'; import { DEBUG, OPTIMIZED } from '../constants'; @@ -7,7 +8,7 @@ import { DEBUG, OPTIMIZED } from '../constants'; export default function validImpressionsMode(log: ILogger, impressionsMode: string): SplitIO.ImpressionsMode { impressionsMode = impressionsMode.toUpperCase(); if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) === -1) { - log.error(`You passed an invalid impressionsMode, impressionsMode should be one of the following values: '${DEBUG}' or '${OPTIMIZED}'. Defaulting to '${OPTIMIZED}' mode.`); + log.error(ERROR_38, [DEBUG, OPTIMIZED, OPTIMIZED]); impressionsMode = OPTIMIZED; } diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index 23031832..93d0ea3b 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -1,3 +1,4 @@ +import { WARN_21 } from '../../../logger/codesConstants'; import { ILogger } from '../../../logger/types'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-settings'); @@ -22,7 +23,7 @@ export function validateIntegrations(settings: { log: ILogger, integrations?: an // Log a warning if at least one item is invalid const invalids = integrations.length - validIntegrations.length; - if (invalids) log.warn(`${invalids} integration ${invalids === 1 ? 'item' : 'items'} at settings ${invalids === 1 ? 'is' : 'are'} invalid. ${extraWarning || ''}`); + if (invalids) log.warn(WARN_21, [invalids, invalids === 1 ? 'item' : 'items', invalids === 1 ? 'is' : 'are', extraWarning || '']); return validIntegrations; } diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index e950ba48..793267c0 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -3,6 +3,7 @@ import { validateSplits } from '../inputValidation/splits'; import { ISplitFiltersValidation } from '../../dtos/types'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; +import { WARN_22, WARN_24, WARN_23, DEBUG_51 } from '../../logger/codesConstants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); @@ -98,12 +99,12 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: if (!maybeSplitFilters) return res; // Warn depending on the mode if (mode !== STANDALONE_MODE) { - log.warn(`Factory instantiation: split filters have been configured but will have no effect if mode is not '${STANDALONE_MODE}', since synchronization is being deferred to an external tool.`); + log.warn(WARN_22, [STANDALONE_MODE]); return res; } // Check collection type if (!Array.isArray(maybeSplitFilters) || maybeSplitFilters.length === 0) { - log.warn('Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'); + log.warn(WARN_24); return res; } @@ -114,7 +115,7 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: res.groupedFilters[filter.type as SplitIO.SplitFilterType] = res.groupedFilters[filter.type as SplitIO.SplitFilterType].concat(filter.values); return true; } else { - log.warn(`Factory instantiation: split filter at position '${index}' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'.`); + log.warn(WARN_23, [index]); } return false; }); @@ -126,7 +127,7 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: // build query string res.queryString = queryStringBuilder(res.groupedFilters); - log.debug(`Factory instantiation: splits filtering criteria is '${res.queryString}'.`); + log.debug(DEBUG_51, [res.queryString]); return res; } diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index 40bfd221..a52b07ea 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -1,6 +1,7 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS'; import { ISettings } from '../../../types'; import { ILogger } from '../../../logger/types'; +import { WARN_25 } from '../../../logger/codesConstants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-settings'); @@ -18,7 +19,7 @@ export function validateStorageCS(settings: { log: ILogger, storage?: any }): IS // @TODO validate its API (Splits cache, MySegments cache, etc) when supporting custom storages if (storage) { if (typeof storage === 'function') return storage; - log.warn('The provided storage is invalid. Fallbacking into default MEMORY storage'); + log.warn(WARN_25); } // return default InMemory storage if provided one is not valid From 48728154560e42d8cf16f4902f41aa0c29bf31cf Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 10 Mar 2021 19:57:36 -0300 Subject: [PATCH 25/58] extracted strings into constants file --- src/evaluator/combiners/and.ts | 2 +- src/evaluator/combiners/ifelseif.ts | 2 +- src/evaluator/condition/engineUtils.ts | 2 +- src/evaluator/matchers/all.ts | 2 +- src/evaluator/matchers/between.ts | 2 +- src/evaluator/matchers/boolean.ts | 2 +- src/evaluator/matchers/cont_all.ts | 2 +- src/evaluator/matchers/cont_any.ts | 2 +- src/evaluator/matchers/cont_str.ts | 2 +- src/evaluator/matchers/dependency.ts | 2 +- src/evaluator/matchers/eq.ts | 2 +- src/evaluator/matchers/eq_set.ts | 2 +- src/evaluator/matchers/ew.ts | 2 +- src/evaluator/matchers/gte.ts | 2 +- src/evaluator/matchers/lte.ts | 2 +- src/evaluator/matchers/part_of.ts | 2 +- src/evaluator/matchers/segment.ts | 2 +- src/evaluator/matchers/string.ts | 2 +- src/evaluator/matchers/sw.ts | 2 +- src/evaluator/matchers/whitelist.ts | 2 +- src/evaluator/value/index.ts | 2 +- src/evaluator/value/sanitize.ts | 2 +- src/listeners/browser.ts | 2 +- src/listeners/node.ts | 2 +- src/logger/browser/debugLogger.ts | 8 - src/logger/browser/errorLogger.ts | 5 - src/logger/browser/infoLogger.ts | 7 - src/logger/browser/warnLogger.ts | 6 - src/logger/codesConstants.ts | 118 -------------- src/logger/codesConstantsBrowser.ts | 3 - src/logger/codesConstantsNode.ts | 21 --- src/logger/codesDebug.ts | 44 ------ src/logger/codesDebugBrowser.ts | 6 - src/logger/codesDebugNode.ts | 14 -- src/logger/codesError.ts | 36 ----- src/logger/codesErrorNode.ts | 7 - src/logger/codesInfo.ts | 26 ---- src/logger/codesWarn.ts | 28 ---- src/logger/codesWarnNode.ts | 5 - src/logger/constants.ts | 147 ++++++++++++++++++ src/logger/index.ts | 17 +- src/logger/sdkLogger.ts | 2 +- src/logger/types.ts | 8 +- src/readiness/sdkReadinessManager.ts | 2 +- src/sdkClient/client.ts | 2 +- src/sdkClient/sdkClientMethod.ts | 2 +- src/sdkClient/sdkClientMethodCS.ts | 2 +- src/sdkClient/sdkClientMethodCSWithTT.ts | 2 +- src/sdkFactory/index.ts | 2 +- src/services/splitHttpClient.ts | 2 +- .../splitsParser/splitsParserFromFile.ts | 2 +- .../offline/syncTasks/fromObjectSyncTask.ts | 2 +- src/sync/polling/pollingManagerCS.ts | 2 +- src/sync/polling/pollingManagerSS.ts | 4 +- .../polling/syncTasks/mySegmentsSyncTask.ts | 2 +- .../polling/syncTasks/segmentsSyncTask.ts | 2 +- src/sync/polling/syncTasks/splitsSyncTask.ts | 2 +- src/sync/streaming/SSEHandler/index.ts | 2 +- src/sync/streaming/pushManager.ts | 2 +- src/sync/streaming/pushManagerCS.ts | 2 +- src/sync/streaming/pushManagerSS.ts | 2 +- src/sync/submitters/eventsSyncTask.ts | 2 +- src/sync/submitters/submitterSyncTask.ts | 2 +- src/sync/syncManagerOnline.ts | 2 +- src/sync/syncTask.ts | 2 +- src/trackers/eventTracker.ts | 2 +- src/trackers/impressionsTracker.ts | 2 +- src/utils/inputValidation/attributes.ts | 2 +- src/utils/inputValidation/event.ts | 2 +- src/utils/inputValidation/eventProperties.ts | 2 +- src/utils/inputValidation/eventValue.ts | 2 +- src/utils/inputValidation/isOperational.ts | 2 +- src/utils/inputValidation/key.ts | 2 +- src/utils/inputValidation/split.ts | 2 +- src/utils/inputValidation/splitExistance.ts | 2 +- src/utils/inputValidation/splits.ts | 2 +- src/utils/inputValidation/trafficType.ts | 2 +- .../inputValidation/trafficTypeExistance.ts | 2 +- .../settingsValidation/impressionsMode.ts | 2 +- .../settingsValidation/integrations/common.ts | 2 +- src/utils/settingsValidation/splitFilters.ts | 2 +- .../settingsValidation/storage/storageCS.ts | 2 +- 82 files changed, 223 insertions(+), 413 deletions(-) delete mode 100644 src/logger/browser/debugLogger.ts delete mode 100644 src/logger/browser/errorLogger.ts delete mode 100644 src/logger/browser/infoLogger.ts delete mode 100644 src/logger/browser/warnLogger.ts delete mode 100644 src/logger/codesConstants.ts delete mode 100644 src/logger/codesConstantsBrowser.ts delete mode 100644 src/logger/codesConstantsNode.ts delete mode 100644 src/logger/codesDebug.ts delete mode 100644 src/logger/codesDebugBrowser.ts delete mode 100644 src/logger/codesDebugNode.ts delete mode 100644 src/logger/codesError.ts delete mode 100644 src/logger/codesErrorNode.ts delete mode 100644 src/logger/codesInfo.ts delete mode 100644 src/logger/codesWarn.ts delete mode 100644 src/logger/codesWarnNode.ts create mode 100644 src/logger/constants.ts diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index 6549594e..f21653d2 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -5,7 +5,7 @@ import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { MaybeThenable } from '../../dtos/types'; import { IMatcher } from '../types'; -import { DEBUG_0 } from '../../logger/codesConstants'; +import { DEBUG_0 } from '../../logger/constants'; export default function andCombinerContext(log: ILogger, matchers: IMatcher[]) { diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index a680cb13..0f2f202a 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -7,7 +7,7 @@ import * as LabelsConstants from '../../utils/labels'; import { CONTROL } from '../../utils/constants'; import { SplitIO } from '../../types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; -import { DEBUG_1, DEBUG_2, ERROR_0 } from '../../logger/codesConstants'; +import { DEBUG_1, DEBUG_2, ERROR_0 } from '../../logger/constants'; export default function ifElseIfCombinerContext(log: ILogger, predicates: IEvaluator[]): IEvaluator { diff --git a/src/evaluator/condition/engineUtils.ts b/src/evaluator/condition/engineUtils.ts index da1e024b..b8b842de 100644 --- a/src/evaluator/condition/engineUtils.ts +++ b/src/evaluator/condition/engineUtils.ts @@ -1,4 +1,4 @@ -import { DEBUG_3 } from '../../logger/codesConstants'; +import { DEBUG_3 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { bucket } from '../../utils/murmur3/murmur3'; // import { logFactory } from '../../logger/sdkLogger'; diff --git a/src/evaluator/matchers/all.ts b/src/evaluator/matchers/all.ts index ca78a5d2..df609cab 100644 --- a/src/evaluator/matchers/all.ts +++ b/src/evaluator/matchers/all.ts @@ -1,4 +1,4 @@ -import { DEBUG_4 } from '../../logger/codesConstants'; +import { DEBUG_4 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/between.ts b/src/evaluator/matchers/between.ts index 6429b12e..cd40a24d 100644 --- a/src/evaluator/matchers/between.ts +++ b/src/evaluator/matchers/between.ts @@ -1,5 +1,5 @@ import { IBetweenMatcherData } from '../../dtos/types'; -import { DEBUG_5 } from '../../logger/codesConstants'; +import { DEBUG_5 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/boolean.ts b/src/evaluator/matchers/boolean.ts index 67ba6645..74bfd378 100644 --- a/src/evaluator/matchers/boolean.ts +++ b/src/evaluator/matchers/boolean.ts @@ -1,4 +1,4 @@ -import { DEBUG_6 } from '../../logger/codesConstants'; +import { DEBUG_6 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/cont_all.ts b/src/evaluator/matchers/cont_all.ts index d292b7a4..5c2a4289 100644 --- a/src/evaluator/matchers/cont_all.ts +++ b/src/evaluator/matchers/cont_all.ts @@ -1,4 +1,4 @@ -import { DEBUG_7 } from '../../logger/codesConstants'; +import { DEBUG_7 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/cont_any.ts b/src/evaluator/matchers/cont_any.ts index f131c103..beaa3b2b 100644 --- a/src/evaluator/matchers/cont_any.ts +++ b/src/evaluator/matchers/cont_any.ts @@ -1,4 +1,4 @@ -import { DEBUG_8 } from '../../logger/codesConstants'; +import { DEBUG_8 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/cont_str.ts b/src/evaluator/matchers/cont_str.ts index 85231cd3..a126932f 100644 --- a/src/evaluator/matchers/cont_str.ts +++ b/src/evaluator/matchers/cont_str.ts @@ -2,7 +2,7 @@ import { isString } from '../../utils/lang'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; -import { DEBUG_9 } from '../../logger/codesConstants'; +import { DEBUG_9 } from '../../logger/constants'; export default function containsStringMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function containsStringMatcher(runtimeAttr: string): boolean { diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index 28dc8fa2..4795b61f 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -5,7 +5,7 @@ import { IStorageAsync, IStorageSync } from '../../storages/types'; import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { IDependencyMatcherValue, IEvaluation, ISplitEvaluator } from '../types'; -import { DEBUG_10, DEBUG_11 } from '../../logger/codesConstants'; +import { DEBUG_10, DEBUG_11 } from '../../logger/constants'; export default function dependencyMatcherContext(log: ILogger, { split, treatments }: IDependencyMatcherData, storage: IStorageSync | IStorageAsync) { diff --git a/src/evaluator/matchers/eq.ts b/src/evaluator/matchers/eq.ts index fdd91f7a..ef74e56e 100644 --- a/src/evaluator/matchers/eq.ts +++ b/src/evaluator/matchers/eq.ts @@ -1,4 +1,4 @@ -import { DEBUG_12 } from '../../logger/codesConstants'; +import { DEBUG_12 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/eq_set.ts b/src/evaluator/matchers/eq_set.ts index 7b700789..d552a2d5 100644 --- a/src/evaluator/matchers/eq_set.ts +++ b/src/evaluator/matchers/eq_set.ts @@ -1,4 +1,4 @@ -import { DEBUG_13 } from '../../logger/codesConstants'; +import { DEBUG_13 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/ew.ts b/src/evaluator/matchers/ew.ts index f14d4088..2d94d4b2 100644 --- a/src/evaluator/matchers/ew.ts +++ b/src/evaluator/matchers/ew.ts @@ -1,4 +1,4 @@ -import { DEBUG_14 } from '../../logger/codesConstants'; +import { DEBUG_14 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/gte.ts b/src/evaluator/matchers/gte.ts index 30d81722..dd5b4abf 100644 --- a/src/evaluator/matchers/gte.ts +++ b/src/evaluator/matchers/gte.ts @@ -1,4 +1,4 @@ -import { DEBUG_15 } from '../../logger/codesConstants'; +import { DEBUG_15 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/lte.ts b/src/evaluator/matchers/lte.ts index ba69e68d..d3804088 100644 --- a/src/evaluator/matchers/lte.ts +++ b/src/evaluator/matchers/lte.ts @@ -1,4 +1,4 @@ -import { DEBUG_16 } from '../../logger/codesConstants'; +import { DEBUG_16 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/part_of.ts b/src/evaluator/matchers/part_of.ts index d4aaed73..7b804144 100644 --- a/src/evaluator/matchers/part_of.ts +++ b/src/evaluator/matchers/part_of.ts @@ -2,7 +2,7 @@ import { findIndex } from '../../utils/lang'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; -import { DEBUG_17 } from '../../logger/codesConstants'; +import { DEBUG_17 } from '../../logger/constants'; export default function partOfMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function partOfMatcher(runtimeAttr: string[]): boolean { diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index 3b8216aa..23efc8de 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -4,7 +4,7 @@ import { ISegmentsCacheBase } from '../../storages/types'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; -import { DEBUG_18, DEBUG_19 } from '../../logger/codesConstants'; +import { DEBUG_18, DEBUG_19 } from '../../logger/constants'; export default function matcherSegmentContext(log: ILogger, segmentName: string, storage: { segments: ISegmentsCacheBase }) { diff --git a/src/evaluator/matchers/string.ts b/src/evaluator/matchers/string.ts index 8a301fdc..c8353323 100644 --- a/src/evaluator/matchers/string.ts +++ b/src/evaluator/matchers/string.ts @@ -1,4 +1,4 @@ -import { DEBUG_21, DEBUG_20 } from '../../logger/codesConstants'; +import { DEBUG_21, DEBUG_20 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/sw.ts b/src/evaluator/matchers/sw.ts index 1a19ff75..082b9ab8 100644 --- a/src/evaluator/matchers/sw.ts +++ b/src/evaluator/matchers/sw.ts @@ -1,4 +1,4 @@ -import { DEBUG_22 } from '../../logger/codesConstants'; +import { DEBUG_22 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; diff --git a/src/evaluator/matchers/whitelist.ts b/src/evaluator/matchers/whitelist.ts index b45dc8b8..0da714de 100644 --- a/src/evaluator/matchers/whitelist.ts +++ b/src/evaluator/matchers/whitelist.ts @@ -2,7 +2,7 @@ import { setToArray, ISet } from '../../utils/lang/sets'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; -import { DEBUG_23 } from '../../logger/codesConstants'; +import { DEBUG_23 } from '../../logger/constants'; export default function whitelistMatcherContext(log: ILogger, ruleAttr: ISet) /*: Function */ { return function whitelistMatcher(runtimeAttr: string): boolean { diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index 12d3b9c1..eae699e4 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -4,7 +4,7 @@ import { IMatcherDto } from '../types'; // const log = logFactory('splitio-engine:value'); import { ILogger } from '../../logger/types'; import sanitizeValue from './sanitize'; -import { DEBUG_24, WARN_1, WARN_0 } from '../../logger/codesConstants'; +import { DEBUG_24, WARN_1, WARN_0 } from '../../logger/constants'; function parseValue(log: ILogger, key: string, attributeName: string | null, attributes: SplitIO.Attributes) { let value = undefined; diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index d8db57a6..a05e023f 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -6,7 +6,7 @@ import { ILogger } from '../../logger/types'; import { isObject, uniq, toString, toNumber } from '../../utils/lang'; import { zeroSinceHH, zeroSinceSS } from '../convertions'; import { matcherTypes, dataTypes } from '../matchers/matcherTypes'; -import { DEBUG_25 } from '../../logger/codesConstants'; +import { DEBUG_25 } from '../../logger/constants'; function sanitizeNumber(val: any): number | undefined { const num = toNumber(val); diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index ff5910b5..78a2b1a1 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -10,7 +10,7 @@ import { ImpressionsPayload } from '../sync/submitters/types'; import { MaybeThenable } from '../dtos/types'; import { OPTIMIZED, DEBUG } from '../utils/constants'; import objectAssign from 'object-assign'; -import { DEBUG_26, DEBUG_27 } from '../logger/codesConstantsBrowser'; +import { DEBUG_26, DEBUG_27 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client:cleanup'); diff --git a/src/listeners/node.ts b/src/listeners/node.ts index ade705da..e61e918a 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -3,7 +3,7 @@ import { ISignalListener } from './types'; import thenable from '../utils/promise/thenable'; import { MaybeThenable } from '../dtos/types'; import { ISettings } from '../types'; -import { DEBUG_28, DEBUG_29, DEBUG_30, ERROR_1 } from '../logger/codesConstantsNode'; +import { DEBUG_28, DEBUG_29, DEBUG_30, ERROR_1 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client:cleanup'); diff --git a/src/logger/browser/debugLogger.ts b/src/logger/browser/debugLogger.ts deleted file mode 100644 index 5ebeb427..00000000 --- a/src/logger/browser/debugLogger.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Logger } from '../index'; -import { codesError } from '../codesError'; -import { codesWarn } from '../codesWarn'; -import { codesInfo } from '../codesInfo'; -import { codesDebug } from '../codesDebug'; -import { _Map } from '../../utils/lang/maps'; - -export const debugLogger = new Logger('splitio', { logLevel: 'DEBUG' }, new _Map(codesError.concat(codesWarn).concat(codesInfo).concat(codesDebug))); diff --git a/src/logger/browser/errorLogger.ts b/src/logger/browser/errorLogger.ts deleted file mode 100644 index b132f192..00000000 --- a/src/logger/browser/errorLogger.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Logger } from '../index'; -import { codesError } from '../codesError'; -import { _Map } from '../../utils/lang/maps'; - -export const errorLogger = new Logger('splitio', { logLevel: 'ERROR' }, new _Map(codesError)); diff --git a/src/logger/browser/infoLogger.ts b/src/logger/browser/infoLogger.ts deleted file mode 100644 index f001b9bb..00000000 --- a/src/logger/browser/infoLogger.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Logger } from '../index'; -import { codesError } from '../codesError'; -import { codesWarn } from '../codesWarn'; -import { codesInfo } from '../codesInfo'; -import { _Map } from '../../utils/lang/maps'; - -export const infoLogger = new Logger('splitio', { logLevel: 'INFO' }, new _Map(codesError.concat(codesWarn).concat(codesInfo))); diff --git a/src/logger/browser/warnLogger.ts b/src/logger/browser/warnLogger.ts deleted file mode 100644 index 1ba1667b..00000000 --- a/src/logger/browser/warnLogger.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Logger } from '../index'; -import { codesError } from '../codesError'; -import { codesWarn } from '../codesWarn'; -import { _Map } from '../../utils/lang/maps'; - -export const warnLogger = new Logger('splitio', { logLevel: 'WARN' }, new _Map(codesError.concat(codesWarn))); diff --git a/src/logger/codesConstants.ts b/src/logger/codesConstants.ts deleted file mode 100644 index 9852e7c8..00000000 --- a/src/logger/codesConstants.ts +++ /dev/null @@ -1,118 +0,0 @@ -export const DEBUG_0 = 0; -export const DEBUG_1 = 1; -export const DEBUG_2 = 2; -export const DEBUG_3 = 3; -export const DEBUG_4 = 4; -export const DEBUG_5 = 5; -export const DEBUG_6 = 6; -export const DEBUG_7 = 7; -export const DEBUG_8 = 8; -export const DEBUG_9 = 9; -export const DEBUG_10 = 10; -export const DEBUG_11 = 11; -export const DEBUG_12 = 12; -export const DEBUG_13 = 13; -export const DEBUG_14 = 14; -export const DEBUG_15 = 15; -export const DEBUG_16 = 16; -export const DEBUG_17 = 17; -export const DEBUG_18 = 18; -export const DEBUG_19 = 19; -export const DEBUG_20 = 20; -export const DEBUG_21 = 21; -export const DEBUG_22 = 22; -export const DEBUG_23 = 23; -export const DEBUG_24 = 24; -export const DEBUG_25 = 25; -export const DEBUG_31 = 31; -export const DEBUG_32 = 32; -export const DEBUG_33 = 33; -export const DEBUG_36 = 36; -export const DEBUG_42 = 42; -export const DEBUG_43 = 43; -export const DEBUG_44 = 44; -export const DEBUG_45 = 45; -export const DEBUG_46 = 46; -export const DEBUG_47 = 47; -export const DEBUG_48 = 48; -export const DEBUG_49 = 49; -export const DEBUG_50 = 50; -export const DEBUG_51 = 51; -export const INFO_0 = 100; -export const INFO_1 = 101; -export const INFO_2 = 102; -export const INFO_3 = 103; -export const INFO_4 = 104; -export const INFO_5 = 105; -export const INFO_6 = 106; -export const INFO_7 = 107; -export const INFO_8 = 108; -export const INFO_9 = 109; -export const INFO_10 = 110; -export const INFO_11 = 111; -export const INFO_12 = 112; -export const INFO_13 = 113; -export const INFO_14 = 114; -export const INFO_15 = 115; -export const INFO_16 = 116; -export const INFO_17 = 117; -export const INFO_18 = 118; -export const INFO_19 = 119; -export const INFO_20 = 120; -export const INFO_21 = 121; -export const WARN_0 = 200; -export const WARN_1 = 201; -export const WARN_2 = 202; -export const WARN_4 = 204; -export const WARN_5 = 205; -export const WARN_6 = 206; -export const WARN_7 = 207; -export const WARN_8 = 208; -export const WARN_9 = 209; -export const WARN_10 = 210; -export const WARN_11 = 211; -export const WARN_12 = 212; -export const WARN_13 = 213; -export const WARN_14 = 214; -export const WARN_15 = 215; -export const WARN_17 = 217; -export const WARN_18 = 218; -export const WARN_19 = 219; -export const WARN_20 = 220; -export const WARN_21 = 221; -export const WARN_22 = 222; -export const WARN_23 = 223; -export const WARN_24 = 224; -export const WARN_25 = 225; -export const ERROR_0 = 300; -export const ERROR_2 = 302; -export const ERROR_3 = 303; -export const ERROR_4 = 304; -export const ERROR_5 = 305; -export const ERROR_7 = 307; -export const ERROR_9 = 309; -export const ERROR_10 = 310; -export const ERROR_11 = 311; -export const ERROR_12 = 312; -export const ERROR_13 = 313; -export const ERROR_14 = 314; -export const ERROR_15 = 315; -export const ERROR_16 = 316; -export const ERROR_17 = 317; -export const ERROR_18 = 318; -export const ERROR_19 = 319; -export const ERROR_20 = 320; -export const ERROR_21 = 321; -export const ERROR_22 = 322; -export const ERROR_23 = 323; -export const ERROR_24 = 324; -export const ERROR_25 = 325; -export const ERROR_26 = 326; -export const ERROR_32 = 332; -export const ERROR_33 = 333; -export const ERROR_34 = 334; -export const ERROR_35 = 335; -export const ERROR_36 = 336; -export const ERROR_37 = 337; -export const ERROR_38 = 338; -export const ERROR_39 = 339; diff --git a/src/logger/codesConstantsBrowser.ts b/src/logger/codesConstantsBrowser.ts deleted file mode 100644 index b34771d7..00000000 --- a/src/logger/codesConstantsBrowser.ts +++ /dev/null @@ -1,3 +0,0 @@ -// listeners/browser -export const DEBUG_26 = 26; -export const DEBUG_27 = 27; diff --git a/src/logger/codesConstantsNode.ts b/src/logger/codesConstantsNode.ts deleted file mode 100644 index 614f9c8b..00000000 --- a/src/logger/codesConstantsNode.ts +++ /dev/null @@ -1,21 +0,0 @@ -// listeners/node -export const DEBUG_28 = 28; -export const DEBUG_29 = 29; -export const DEBUG_30 = 30; -export const ERROR_1 = 301; - -// sync/polling/syncTasks/segmentsSyncTask -export const DEBUG_39 = 39; -export const DEBUG_40 = 40; -export const DEBUG_41 = 41; -export const ERROR_8 = 308; - -// sync/offline/splitsParser/splitsParserFromFile -export const DEBUG_34 = 34; -export const DEBUG_35 = 35; -export const ERROR_6 = 306; -export const WARN_3 = 203; - -// sync/polling/pollingManagerSS.ts -export const DEBUG_37 = 37; -export const DEBUG_38 = 38; diff --git a/src/logger/codesDebug.ts b/src/logger/codesDebug.ts deleted file mode 100644 index 02ec3d84..00000000 --- a/src/logger/codesDebug.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_31, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_51 } from './codesConstants'; - -export const codesDebug: [number, string][] = [ - [DEBUG_0, 'splitio-engine:combiner => [andCombiner] evaluates to %s'], - [DEBUG_1, 'splitio-engine:combiner => Treatment found: %s'], - [DEBUG_2, 'splitio-engine:combiner => All predicates evaluated, no treatment found.'], - [DEBUG_3, 'splitio-engine => [engine] using algo \'murmur\' bucket %s for key %s using seed %s - treatment %s'], - [DEBUG_4, 'splitio-engine:matcher => [allMatcher] is always true'], - [DEBUG_5, 'splitio-engine:matcher => [betweenMatcher] is %s between %s and %s? %s'], - [DEBUG_6, 'splitio-engine:matcher => [booleanMatcher] %s === %s'], - [DEBUG_7, 'splitio-engine:matcher => [containsAllMatcher] %s contains all elements of %s? %s'], - [DEBUG_8, 'splitio-engine:matcher => [containsAnyMatcher] %s contains at least an element of %s? %s'], - [DEBUG_9, 'splitio-engine:matcher => [containsStringMatcher] %s contains %s? %s'], - [DEBUG_10, 'splitio-engine:matcher => [dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], - [DEBUG_11, 'splitio-engine:matcher => [dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], - [DEBUG_12, 'splitio-engine:matcher => [equalToMatcher] is %s equal to %s? %s'], - [DEBUG_13, 'splitio-engine:matcher => [equalToSetMatcher] is %s equal to set %s? %s'], - [DEBUG_14, 'splitio-engine:matcher => [endsWithMatcher] %s ends with %s? %s'], - [DEBUG_15, 'splitio-engine:matcher => [greaterThanEqualMatcher] is %s greater than %s? %s'], - [DEBUG_16, 'splitio-engine:matcher => [lessThanEqualMatcher] is %s less than %s? %s'], - [DEBUG_17, 'splitio-engine:matcher => [partOfMatcher] %s is part of %s? %s'], - [DEBUG_18, 'splitio-engine:matcher => [asyncSegmentMatcher] evaluated %s / %s => %s'], - [DEBUG_19, 'splitio-engine:matcher => [segmentMatcher] evaluated %s / %s => %s'], - [DEBUG_20, 'splitio-engine:matcher => [stringMatcher] does %s matches with %s? %s'], - [DEBUG_21, 'splitio-engine:matcher => [stringMatcher] %s is an invalid regex'], - [DEBUG_22, 'splitio-engine:matcher => [startsWithMatcher] %s starts with %s? %s'], - [DEBUG_23, 'splitio-engine:matcher => [whitelistMatcher] evaluated %s in [%s] => %s'], - [DEBUG_24, 'splitio-engine:value => Extracted attribute [%s], [%s] will be used for matching.'], - [DEBUG_25, 'splitio-engine:sanitize => Attempted to sanitize [%s] which should be of type [%s]. \n Sanitized and processed value => [%s]'], - [DEBUG_31, 'splitio => Retrieving SDK client.'], - [DEBUG_32, 'splitio => Retrieving default SDK client.'], // @TODO remove and use 'splitio => Retrieving SDK client.' - [DEBUG_33, 'splitio => Retrieving existing SDK client.'], - [DEBUG_36, 'splitio-producer:offline => Splits data: '], - [DEBUG_42, 'splitio-sync:split-changes => Spin up split update using since = %s'], - [DEBUG_43, 'splitio-sync:split-changes => New splits %s'], - [DEBUG_44, 'splitio-sync:split-changes => Removed splits %s'], - [DEBUG_45, 'splitio-sync:split-changes => Segment names collected %s'], - [DEBUG_46, 'splitio-sync:sse-handler => New SSE message received, with data: %s.'], - [DEBUG_47, 'splitio-sync:task => Starting %s. Running each %s millis'], - [DEBUG_48, 'splitio-sync:task => Running %s'], - [DEBUG_49, 'splitio-sync:task => Stopping %s'], - [DEBUG_50, 'splitio-client:impressions-tracker => Successfully stored %s impression%s.'], - [DEBUG_51, 'Factory instantiation: splits filtering criteria is \'%s\'.'] -]; diff --git a/src/logger/codesDebugBrowser.ts b/src/logger/codesDebugBrowser.ts deleted file mode 100644 index 3e7be5d5..00000000 --- a/src/logger/codesDebugBrowser.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { DEBUG_26, DEBUG_27 } from './codesConstantsBrowser'; - -export const codesDebugBrowser: [number, string][] = [ - [DEBUG_26, 'splitio-client:cleanup => Registering flush handler when unload page event is triggered.'], - [DEBUG_27, 'splitio-client:cleanup => Deregistering flush handler when unload page event is triggered.'], -]; diff --git a/src/logger/codesDebugNode.ts b/src/logger/codesDebugNode.ts deleted file mode 100644 index 890d7207..00000000 --- a/src/logger/codesDebugNode.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DEBUG_28, DEBUG_29, DEBUG_30, DEBUG_39, DEBUG_40, DEBUG_41, DEBUG_34, DEBUG_35, DEBUG_37, DEBUG_38 } from './codesConstantsNode'; - -export const codesDebugNode: [number, string][] = [ - [DEBUG_28, 'splitio-client:cleanup => Registering cleanup handlers.'], - [DEBUG_29, 'splitio-client:cleanup => Deregistering cleanup handlers.'], - [DEBUG_30, 'splitio-client:cleanup => Split SDK graceful shutdown after SIGTERM.'], - [DEBUG_39, 'splitio-sync:segment-changes => Processed %s with till = %s. Added: %s. Removed: %s'], - [DEBUG_40, 'splitio-sync:segment-changes => Processing segment %s'], - [DEBUG_41, 'splitio-sync:segment-changes => Started segments update'], - [DEBUG_34, 'splitio-offline:splits-fetcher => Ignoring empty line or comment at #%s'], - [DEBUG_35, 'splitio-offline:splits-fetcher => Ignoring line since it does not have exactly two columns #%s'], - [DEBUG_37, 'splitio-sync:polling-manager => Splits will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? - [DEBUG_38, 'splitio-sync:polling-manager => Segments will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? -]; diff --git a/src/logger/codesError.ts b/src/logger/codesError.ts deleted file mode 100644 index 303df195..00000000 --- a/src/logger/codesError.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ERROR_0, ERROR_2, ERROR_3, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_13, ERROR_14, ERROR_15, ERROR_16, ERROR_17, ERROR_18, ERROR_19, ERROR_20, ERROR_21, ERROR_22, ERROR_23, ERROR_24, ERROR_25, ERROR_26, ERROR_32, ERROR_33, ERROR_34, ERROR_35, ERROR_36, ERROR_37, ERROR_38, ERROR_39 } from './codesConstants'; - -export const codesError: [number, string][] = [ - [ERROR_0, 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'], - [ERROR_2, 'splitio-utils:logger => Invalid Log Level - No changes to the logs will be applied.'], - [ERROR_3, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], - [ERROR_4, 'splitio => Manager instance is not available. Provide the manager module on settings.'], - [ERROR_5, 'splitio-services:service => %s The SDK will not get ready.'], - [ERROR_7, 'splitio-producer:offline => There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], - [ERROR_9, 'splitio-sync:sse-handler => Fail to connect to streaming, with error message: %s'], - [ERROR_10, 'splitio-sync:push-manager => Failed to authenticate for streaming. Error: "%s".'], - [ERROR_11, 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'], - [ERROR_12, 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'], - [ERROR_13, '%s: attributes must be a plain object.'], - [ERROR_14, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], - [ERROR_15, '%s: you passed a null or undefined event_type, event_type must be a non-empty string.'], - [ERROR_16, '%s: you passed an invalid event_type, event_type must be a non-empty string.'], - [ERROR_17, '%s: you passed an empty event_type, event_type must be a non-empty string.'], - [ERROR_18, '%s: properties must be a plain object.'], - [ERROR_19, '%s: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'], - [ERROR_20, '%s: value must be a finite number.'], - [ERROR_21, 'Client has already been destroyed - no calls possible.'], - [ERROR_22, '%s: you passed a null or undefined %s, %s must be a non-empty string.'], - [ERROR_23, '%s: %s too long, %s must be 250 characters or less.'], - [ERROR_24, '%s: you passed an invalid %s type, %s must be a non-empty string.'], - [ERROR_25, '%s: you passed an empty string, %s must be a non-empty string.'], - [ERROR_26, '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'], - [ERROR_32, '%s: you passed an invalid %s, %s must be a non-empty string.'], - [ERROR_33, '%s: you passed an empty %s, %s must be a non-empty string.'], - [ERROR_34, '%s: %s must be a non-empty array.'], - [ERROR_35, '%s: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.'], - [ERROR_36, '%s: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.'], - [ERROR_37, '%s: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.'], - [ERROR_38, 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: \'%s\' or \'%s\'. Defaulting to \'%s\' mode.'], - [ERROR_39, 'Response status is not OK. Status: %s. URL: %s. Message: %s'] -]; diff --git a/src/logger/codesErrorNode.ts b/src/logger/codesErrorNode.ts deleted file mode 100644 index b56218bd..00000000 --- a/src/logger/codesErrorNode.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ERROR_1, ERROR_8, ERROR_6 } from './codesConstantsNode'; - -export const codesErrorNode: [number, string][] = [ - [ERROR_1, 'splitio-client:cleanup => Error with Split graceful shutdown: %s'], - [ERROR_8, 'splitio-sync:segment-changes => Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'], - [ERROR_6, 'splitio-offline:splits-fetcher => Ignoring entry on YAML since the format is incorrect.'], -]; diff --git a/src/logger/codesInfo.ts b/src/logger/codesInfo.ts deleted file mode 100644 index f19f3472..00000000 --- a/src/logger/codesInfo.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { INFO_0, INFO_1, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21 } from './codesConstants'; - -export const codesInfo: [number, string][] = [ - [INFO_0, 'Split SDK is ready from cache.'], - [INFO_1, 'Split SDK is ready.'], - [INFO_2, 'splitio-client => Split: %s. Key: %s. Evaluation: %s. Label: %s'], - [INFO_3, 'splitio-client => Queueing corresponding impression.'], - [INFO_4, 'splitio => New shared client instance created.'], - [INFO_5, 'splitio => New Split SDK instance created.'], - [INFO_6, 'splitio => Manager instance retrieved.'], - [INFO_7, 'splitio-sync:polling-manager => Turning segments data polling %s.'], - [INFO_8, 'splitio-sync:polling-manager => Starting polling'], - [INFO_9, 'splitio-sync:polling-manager => Stopping polling'], - [INFO_10, 'splitio-sync:split-changes => Retrying download of splits #%s. Reason: %s'], - [INFO_11, 'splitio-sync:push-manager => Refreshing streaming token in %s seconds.'], - [INFO_12, 'splitio-sync:push-manager => Attempting to reconnect in %s seconds.'], - [INFO_13, 'splitio-sync:push-manager => Connecting to push streaming.'], - [INFO_14, 'splitio-sync:push-manager => Streaming is not available. Switching to polling mode.'], - [INFO_15, 'splitio-sync:push-manager => Disconnecting from push streaming.'], - [INFO_16, 'splitio-sync:submitters => Flushing full events queue and reseting timer.'], - [INFO_17, 'splitio-sync:submitters => Pushing %s %s.'], - [INFO_18, 'splitio-sync:sync-manager => Streaming not available. Starting periodic fetch of data.'], - [INFO_19, 'splitio-sync:sync-manager => Streaming couldn\'t connect. Continue periodic fetch of data.'], - [INFO_20, 'splitio-sync:sync-manager => PUSH (re)connected. Syncing and stopping periodic fetch of data.'], - [INFO_21, 'splitio-client:event-tracker => Successfully qeued %s'] -]; diff --git a/src/logger/codesWarn.ts b/src/logger/codesWarn.ts deleted file mode 100644 index 2649bc2c..00000000 --- a/src/logger/codesWarn.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { WARN_0, WARN_1, WARN_2, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_12, WARN_13, WARN_14, WARN_15, WARN_17, WARN_18, WARN_19, WARN_20, WARN_21, WARN_22, WARN_23, WARN_24, WARN_25 } from './codesConstants'; - -export const codesWarn: [number, string][] = [ - [WARN_0, 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'], - [WARN_1, 'splitio-engine:value => Defined attribute [%s], no attributes received.'], - [WARN_2, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], - [WARN_4, 'splitio-sync:my-segments => Retrying download of segments #%s. Reason: %s'], - [WARN_5, 'splitio-sync:split-changes => Error while doing fetch of Splits. %s'], - [WARN_6, 'splitio-sync:sse-handler => Error parsing SSE error notification: %s'], - [WARN_7, 'splitio-sync:sse-handler => Error parsing new SSE message notification: %s'], - [WARN_8, 'splitio-sync:push-manager => %sFalling back to polling mode.'], - [WARN_9, 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'], - [WARN_10, 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'], - [WARN_11, 'splitio-client:event-tracker => Failed to queue %s'], - [WARN_12, '%s: Property %s is of invalid type. Setting value to null.'], - [WARN_13, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], - [WARN_14, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], - [WARN_15, '%s: %s "%s" is not of type string, converting.'], - [WARN_17, '%s: %s "%s" has extra whitespace, trimming.'], - [WARN_18, '%s: you passed "%s" that does not exist in this environment, please double check what Splits exist in the web console.'], - [WARN_19, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], - [WARN_20, '%s: Traffic Type %s does not have any corresponding Splits in this environment, make sure you\'re tracking your events to a valid traffic type defined in the Split console.'], - [WARN_21, 'splitio-settings => %s integration %s at settings %s invalid. %s'], - [WARN_22, 'Factory instantiation: split filters have been configured but will have no effect if mode is not \'%s\', since synchronization is being deferred to an external tool.'], - [WARN_23, 'Factory instantiation: split filter at position \'%s\' is invalid. It must be an object with a valid filter type (\'byName\' or \'byPrefix\') and a list of \'values\'.'], - [WARN_24, 'Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'], - [WARN_25, 'splitio-settings => The provided storage is invalid. Fallbacking into default MEMORY storage'] -]; diff --git a/src/logger/codesWarnNode.ts b/src/logger/codesWarnNode.ts deleted file mode 100644 index 04288410..00000000 --- a/src/logger/codesWarnNode.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { WARN_3 } from './codesConstantsNode'; - -export const codesWarnNode: [number, string][] = [ - [WARN_3, 'splitio-offline:splits-fetcher => .split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'], -]; diff --git a/src/logger/constants.ts b/src/logger/constants.ts new file mode 100644 index 00000000..76b311ba --- /dev/null +++ b/src/logger/constants.ts @@ -0,0 +1,147 @@ +// commons +export const DEBUG_0 = 'splitio-engine:combiner => [andCombiner] evaluates to %s'; +export const DEBUG_1 = 'splitio-engine:combiner => Treatment found: %s'; +export const DEBUG_2 = 'splitio-engine:combiner => All predicates evaluated, no treatment found.'; +export const DEBUG_3 = 'splitio-engine => [engine] using algo \'murmur\' bucket %s for key %s using seed %s - treatment %s'; +export const DEBUG_4 = 'splitio-engine:matcher => [allMatcher] is always true'; +export const DEBUG_5 = 'splitio-engine:matcher => [betweenMatcher] is %s between %s and %s? %s'; +export const DEBUG_6 = 'splitio-engine:matcher => [booleanMatcher] %s === %s'; +export const DEBUG_7 = 'splitio-engine:matcher => [containsAllMatcher] %s contains all elements of %s? %s'; +export const DEBUG_8 = 'splitio-engine:matcher => [containsAnyMatcher] %s contains at least an element of %s? %s'; +export const DEBUG_9 = 'splitio-engine:matcher => [containsStringMatcher] %s contains %s? %s'; +export const DEBUG_10 = 'splitio-engine:matcher => [dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'; +export const DEBUG_11 = 'splitio-engine:matcher => [dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'; +export const DEBUG_12 = 'splitio-engine:matcher => [equalToMatcher] is %s equal to %s? %s'; +export const DEBUG_13 = 'splitio-engine:matcher => [equalToSetMatcher] is %s equal to set %s? %s'; +export const DEBUG_14 = 'splitio-engine:matcher => [endsWithMatcher] %s ends with %s? %s'; +export const DEBUG_15 = 'splitio-engine:matcher => [greaterThanEqualMatcher] is %s greater than %s? %s'; +export const DEBUG_16 = 'splitio-engine:matcher => [lessThanEqualMatcher] is %s less than %s? %s'; +export const DEBUG_17 = 'splitio-engine:matcher => [partOfMatcher] %s is part of %s? %s'; +export const DEBUG_18 = 'splitio-engine:matcher => [asyncSegmentMatcher] evaluated %s / %s => %s'; +export const DEBUG_19 = 'splitio-engine:matcher => [segmentMatcher] evaluated %s / %s => %s'; +export const DEBUG_20 = 'splitio-engine:matcher => [stringMatcher] does %s matches with %s? %s'; +export const DEBUG_21 = 'splitio-engine:matcher => [stringMatcher] %s is an invalid regex'; +export const DEBUG_22 = 'splitio-engine:matcher => [startsWithMatcher] %s starts with %s? %s'; +export const DEBUG_23 = 'splitio-engine:matcher => [whitelistMatcher] evaluated %s in [%s] => %s'; +export const DEBUG_24 = 'splitio-engine:value => Extracted attribute [%s], [%s] will be used for matching.'; +export const DEBUG_25 = 'splitio-engine:sanitize => Attempted to sanitize [%s] which should be of type [%s]. \n Sanitized and processed value => [%s]'; +export const DEBUG_31 = 'splitio => Retrieving SDK client.'; +export const DEBUG_32 = 'splitio => Retrieving default SDK client.'; // @TODO remove and use 'splitio => Retrieving SDK client.' +export const DEBUG_33 = 'splitio => Retrieving existing SDK client.'; +export const DEBUG_36 = 'splitio-producer:offline => Splits data: '; +export const DEBUG_42 = 'splitio-sync:split-changes => Spin up split update using since = %s'; +export const DEBUG_43 = 'splitio-sync:split-changes => New splits %s'; +export const DEBUG_44 = 'splitio-sync:split-changes => Removed splits %s'; +export const DEBUG_45 = 'splitio-sync:split-changes => Segment names collected %s'; +export const DEBUG_46 = 'splitio-sync:sse-handler => New SSE message received, with data: %s.'; +export const DEBUG_47 = 'splitio-sync:task => Starting %s. Running each %s millis'; +export const DEBUG_48 = 'splitio-sync:task => Running %s'; +export const DEBUG_49 = 'splitio-sync:task => Stopping %s'; +export const DEBUG_50 = 'splitio-client:impressions-tracker => Successfully stored %s impression%s.'; +export const DEBUG_51 = 'Factory instantiation: splits filtering criteria is \'%s\'.'; + +// browser +export const DEBUG_26 = 'splitio-client:cleanup => Registering flush handler when unload page event is triggered.'; +export const DEBUG_27 = 'splitio-client:cleanup => Deregistering flush handler when unload page event is triggered.'; + +// node +export const DEBUG_28 = 'splitio-client:cleanup => Registering cleanup handlers.'; +export const DEBUG_29 = 'splitio-client:cleanup => Deregistering cleanup handlers.'; +export const DEBUG_30 = 'splitio-client:cleanup => Split SDK graceful shutdown after SIGTERM.'; +export const DEBUG_39 = 'splitio-sync:segment-changes => Processed %s with till = %s. Added: %s. Removed: %s'; +export const DEBUG_40 = 'splitio-sync:segment-changes => Processing segment %s'; +export const DEBUG_41 = 'splitio-sync:segment-changes => Started segments update'; +export const DEBUG_34 = 'splitio-offline:splits-fetcher => Ignoring empty line or comment at #%s'; +export const DEBUG_35 = 'splitio-offline:splits-fetcher => Ignoring line since it does not have exactly two columns #%s'; +export const DEBUG_37 = 'splitio-sync:polling-manager => Splits will be refreshed each %s millis'; // @TODO remove since we already log it in syncTask debug log? +export const DEBUG_38 = 'splitio-sync:polling-manager => Segments will be refreshed each %s millis'; // @TODO remove since we already log it in syncTask debug log? + + +export const ERROR_0 = 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'; +export const ERROR_2 = 'splitio-utils:logger => Invalid Log Level - No changes to the logs will be applied.'; +export const ERROR_3 = 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'; +export const ERROR_4 = 'splitio => Manager instance is not available. Provide the manager module on settings.'; +export const ERROR_5 = 'splitio-services:service => %s The SDK will not get ready.'; +export const ERROR_7 = 'splitio-producer:offline => There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'; +export const ERROR_9 = 'splitio-sync:sse-handler => Fail to connect to streaming, with error message: %s'; +export const ERROR_10 = 'splitio-sync:push-manager => Failed to authenticate for streaming. Error: "%s".'; +export const ERROR_11 = 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'; +export const ERROR_12 = 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'; +export const ERROR_13 = '%s: attributes must be a plain object.'; +export const ERROR_14 = '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'; +export const ERROR_15 = '%s: you passed a null or undefined event_type, event_type must be a non-empty string.'; +export const ERROR_16 = '%s: you passed an invalid event_type, event_type must be a non-empty string.'; +export const ERROR_17 = '%s: you passed an empty event_type, event_type must be a non-empty string.'; +export const ERROR_18 = '%s: properties must be a plain object.'; +export const ERROR_19 = '%s: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'; +export const ERROR_20 = '%s: value must be a finite number.'; +export const ERROR_21 = 'Client has already been destroyed - no calls possible.'; +export const ERROR_22 = '%s: you passed a null or undefined %s, %s must be a non-empty string.'; +export const ERROR_23 = '%s: %s too long, %s must be 250 characters or less.'; +export const ERROR_24 = '%s: you passed an invalid %s type, %s must be a non-empty string.'; +export const ERROR_25 = '%s: you passed an empty string, %s must be a non-empty string.'; +export const ERROR_26 = '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'; +export const ERROR_32 = '%s: you passed an invalid %s, %s must be a non-empty string.'; +export const ERROR_33 = '%s: you passed an empty %s, %s must be a non-empty string.'; +export const ERROR_34 = '%s: %s must be a non-empty array.'; +export const ERROR_35 = '%s: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.'; +export const ERROR_36 = '%s: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.'; +export const ERROR_37 = '%s: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.'; +export const ERROR_38 = 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: \'%s\' or \'%s\'. Defaulting to \'%s\' mode.'; +export const ERROR_39 = 'Response status is not OK. Status: %s. URL: %s. Message: %s'; + +// node +export const ERROR_1 = 'splitio-client:cleanup => Error with Split graceful shutdown: %s'; +export const ERROR_8 = 'splitio-sync:segment-changes => Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'; +export const ERROR_6 = 'splitio-offline:splits-fetcher => Ignoring entry on YAML since the format is incorrect.'; + +export const INFO_0 = 'Split SDK is ready from cache.'; +export const INFO_1 = 'Split SDK is ready.'; +export const INFO_2 = 'splitio-client => Split: %s. Key: %s. Evaluation: %s. Label: %s'; +export const INFO_3 = 'splitio-client => Queueing corresponding impression.'; +export const INFO_4 = 'splitio => New shared client instance created.'; +export const INFO_5 = 'splitio => New Split SDK instance created.'; +export const INFO_6 = 'splitio => Manager instance retrieved.'; +export const INFO_7 = 'splitio-sync:polling-manager => Turning segments data polling %s.'; +export const INFO_8 = 'splitio-sync:polling-manager => Starting polling'; +export const INFO_9 = 'splitio-sync:polling-manager => Stopping polling'; +export const INFO_10 = 'splitio-sync:split-changes => Retrying download of splits #%s. Reason: %s'; +export const INFO_11 = 'splitio-sync:push-manager => Refreshing streaming token in %s seconds.'; +export const INFO_12 = 'splitio-sync:push-manager => Attempting to reconnect in %s seconds.'; +export const INFO_13 = 'splitio-sync:push-manager => Connecting to push streaming.'; +export const INFO_14 = 'splitio-sync:push-manager => Streaming is not available. Switching to polling mode.'; +export const INFO_15 = 'splitio-sync:push-manager => Disconnecting from push streaming.'; +export const INFO_16 = 'splitio-sync:submitters => Flushing full events queue and reseting timer.'; +export const INFO_17 = 'splitio-sync:submitters => Pushing %s %s.'; +export const INFO_18 = 'splitio-sync:sync-manager => Streaming not available. Starting periodic fetch of data.'; +export const INFO_19 = 'splitio-sync:sync-manager => Streaming couldn\'t connect. Continue periodic fetch of data.'; +export const INFO_20 = 'splitio-sync:sync-manager => PUSH (re)connected. Syncing and stopping periodic fetch of data.'; +export const INFO_21 = 'splitio-client:event-tracker => Successfully qeued %s'; + +export const WARN_0 = 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'; +export const WARN_1 = 'splitio-engine:value => Defined attribute [%s], no attributes received.'; +export const WARN_2 = 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'; +export const WARN_4 = 'splitio-sync:my-segments => Retrying download of segments #%s. Reason: %s'; +export const WARN_5 = 'splitio-sync:split-changes => Error while doing fetch of Splits. %s'; +export const WARN_6 = 'splitio-sync:sse-handler => Error parsing SSE error notification: %s'; +export const WARN_7 = 'splitio-sync:sse-handler => Error parsing new SSE message notification: %s'; +export const WARN_8 = 'splitio-sync:push-manager => %sFalling back to polling mode.'; +export const WARN_9 = 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'; +export const WARN_10 = 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'; +export const WARN_11 = 'splitio-client:event-tracker => Failed to queue %s'; +export const WARN_12 = '%s: Property %s is of invalid type. Setting value to null.'; +export const WARN_13 = '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'; +export const WARN_14 = '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'; +export const WARN_15 = '%s: %s "%s" is not of type string, converting.'; +export const WARN_17 = '%s: %s "%s" has extra whitespace, trimming.'; +export const WARN_18 = '%s: you passed "%s" that does not exist in this environment, please double check what Splits exist in the web console.'; +export const WARN_19 = '%s: traffic_type_name should be all lowercase - converting string to lowercase.'; +export const WARN_20 = '%s: Traffic Type %s does not have any corresponding Splits in this environment, make sure you\'re tracking your events to a valid traffic type defined in the Split console.'; +export const WARN_21 = 'splitio-settings => %s integration %s at settings %s invalid. %s'; +export const WARN_22 = 'Factory instantiation: split filters have been configured but will have no effect if mode is not \'%s\', since synchronization is being deferred to an external tool.'; +export const WARN_23 = 'Factory instantiation: split filter at position \'%s\' is invalid. It must be an object with a valid filter type (\'byName\' or \'byPrefix\') and a list of \'values\'.'; +export const WARN_24 = 'Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'; +export const WARN_25 = 'splitio-settings => The provided storage is invalid. Fallbacking into default MEMORY storage'; + +// node +export const WARN_3 = 'splitio-offline:splits-fetcher => .split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'; diff --git a/src/logger/index.ts b/src/logger/index.ts index c426881f..eb3e2de4 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -2,7 +2,6 @@ import objectAssign from 'object-assign'; import { ILoggerOptions, ILogger } from './types'; import { find } from '../utils/lang'; import { LogLevel } from '../types'; -import { IMap, _Map } from '../utils/lang/maps'; export const LogLevels: { [level: string]: LogLevel } = { DEBUG: 'DEBUG', @@ -32,37 +31,35 @@ export class Logger implements ILogger { private category: string; public options: Required; - private codes: IMap; - constructor(category: string, options?: ILoggerOptions, codes?: IMap) { + constructor(category: string, options?: ILoggerOptions) { this.category = category; this.options = objectAssign({}, defaultOptions, options); - this.codes = codes || new _Map(); } setLogLevel(logLevel: LogLevel) { this.options.logLevel = logLevel; } - debug(msg: string | number, args?: any[]) { + debug(msg: string, args?: any[]) { this._log(LogLevels.DEBUG, msg, args); } - info(msg: string | number, args?: any[]) { + info(msg: string, args?: any[]) { this._log(LogLevels.INFO, msg, args); } - warn(msg: string | number, args?: any[]) { + warn(msg: string, args?: any[]) { this._log(LogLevels.WARN, msg, args); } - error(msg: string | number, args?: any[]) { + error(msg: string, args?: any[]) { this._log(LogLevels.ERROR, msg, args); } - private _log(level: LogLevel, text: string | number, args?: any[]) { + private _log(level: LogLevel, text: string, args?: any[]) { if (this._shouldLog(level)) { - if (typeof text === 'number') text = sprintf(this.codes.get(text), args); + if (args) text = sprintf(text, args); const formattedText = this._generateLogMessage(level, text); console.log(formattedText); diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 70dbc4fe..94c8b5fa 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -1,7 +1,7 @@ import { LogLevels, isLogLevelString } from './index'; import { ILoggerAPI } from '../types'; import { ILogger } from './types'; -import { ERROR_2 } from './codesConstants'; +import { ERROR_2 } from './constants'; // const log = logFactory('splitio-utils:logger'); diff --git a/src/logger/types.ts b/src/logger/types.ts index d691d255..5fa1d2c4 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -8,11 +8,11 @@ export interface ILoggerOptions { export interface ILogger { setLogLevel(logLevel: LogLevel): void - debug(msg: string | number, args?: any[]): void + debug(msg: string, args?: any[]): void - info(msg: string | number, args?: any[]): void + info(msg: string, args?: any[]): void - warn(msg: string | number, args?: any[]): void + warn(msg: string, args?: any[]): void - error(msg: string | number, args?: any[]): void + error(msg: string, args?: any[]): void } diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index c5370451..97cfd482 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -5,7 +5,7 @@ import { ISdkReadinessManager } from './types'; import { IEventEmitter } from '../types'; import { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from './constants'; import { ILogger } from '../logger/types'; -import { ERROR_3, INFO_0, INFO_1, WARN_2 } from '../logger/codesConstants'; +import { ERROR_3, INFO_0, INFO_1, WARN_2 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory(''); diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index 4750d154..101faa3b 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -8,7 +8,7 @@ import { CONTROL } from '../utils/constants'; import { IClientFactoryParams } from './types'; import { IEvaluationResult } from '../evaluator/types'; import { SplitIO, ImpressionDTO } from '../types'; -import { INFO_2, INFO_3 } from '../logger/codesConstants'; +import { INFO_2, INFO_3 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client'); diff --git a/src/sdkClient/sdkClientMethod.ts b/src/sdkClient/sdkClientMethod.ts index 5e5574c2..4e200b49 100644 --- a/src/sdkClient/sdkClientMethod.ts +++ b/src/sdkClient/sdkClientMethod.ts @@ -1,7 +1,7 @@ import { ISdkClientFactoryParams } from './types'; import { SplitIO } from '../types'; import { sdkClientFactory } from './sdkClient'; -import { DEBUG_31 } from '../logger/codesConstants'; +import { DEBUG_31 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index 17109d02..9cbaea51 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -7,7 +7,7 @@ import { sdkClientFactory } from './sdkClient'; import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; -import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/codesConstants'; +import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index 23fd408c..94c1b638 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -8,7 +8,7 @@ import { sdkClientFactory } from './sdkClient'; import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; -import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/codesConstants'; +import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index dc2adef7..6490c6f4 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -10,7 +10,7 @@ import { getMatching } from '../utils/key'; import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; import { createLoggerAPI } from '../logger/sdkLogger'; -import { INFO_5, INFO_6, ERROR_4 } from '../logger/codesConstants'; +import { INFO_5, INFO_6, ERROR_4 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio'); diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index 5dc2d5e3..3386aebb 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -3,7 +3,7 @@ import { SplitError, SplitNetworkError } from '../utils/lang/errors'; import objectAssign from 'object-assign'; import { IMetadata } from '../dtos/types'; import { ILogger } from '../logger/types'; -import { ERROR_39, ERROR_5 } from '../logger/codesConstants'; +import { ERROR_39, ERROR_5 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-services:service'); diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index e35c8a91..7161c44a 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -9,7 +9,7 @@ import parseCondition, { IMockSplitEntry } from './parseCondition'; import { ISplitPartial } from '../../../dtos/types'; import { SplitIO } from '../../../types'; import { ILogger } from '../../../logger/types'; -import { DEBUG_34, DEBUG_35, ERROR_6, WARN_3 } from '../../../logger/codesConstantsNode'; +import { DEBUG_34, DEBUG_35, ERROR_6, WARN_3 } from '../../../logger/constants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-offline:splits-fetcher'); diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index f9a2aa5d..0c1f2d14 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -8,7 +8,7 @@ import { ISyncTask } from '../../types'; import { ISettings } from '../../../types'; import { CONTROL } from '../../../utils/constants'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; -import { DEBUG_36, ERROR_7 } from '../../../logger/codesConstants'; +import { DEBUG_36, ERROR_7 } from '../../../logger/constants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-producer:offline'); diff --git a/src/sync/polling/pollingManagerCS.ts b/src/sync/polling/pollingManagerCS.ts index 9ef21908..8eb649ef 100644 --- a/src/sync/polling/pollingManagerCS.ts +++ b/src/sync/polling/pollingManagerCS.ts @@ -8,7 +8,7 @@ import splitsSyncTaskFactory from './syncTasks/splitsSyncTask'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants'; -import { INFO_7, INFO_8, INFO_9 } from '../../logger/codesConstants'; +import { INFO_7, INFO_8, INFO_9 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:polling-manager'); diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index e0750bb3..c8acc0c0 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -6,8 +6,8 @@ import { ISplitApi } from '../../services/types'; import { ISettings } from '../../types'; import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types'; import thenable from '../../utils/promise/thenable'; -import { INFO_8, INFO_9 } from '../../logger/codesConstants'; -import { DEBUG_37, DEBUG_38 } from '../../logger/codesConstantsNode'; +import { INFO_8, INFO_9 } from '../../logger/constants'; +import { DEBUG_37, DEBUG_38 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:polling-manager'); diff --git a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts index 108541a9..4524de09 100644 --- a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts @@ -10,7 +10,7 @@ import mySegmentsFetcherFactory from '../fetchers/mySegmentsFetcher'; import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; -import { WARN_4 } from '../../../logger/codesConstants'; +import { WARN_4 } from '../../../logger/constants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:my-segments'); diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index 74dc7378..7438c804 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -11,7 +11,7 @@ import { IFetchSegmentChanges } from '../../../services/types'; import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; -import { DEBUG_41, DEBUG_40, DEBUG_39, ERROR_8 } from '../../../logger/codesConstantsNode'; +import { DEBUG_41, DEBUG_40, DEBUG_39, ERROR_8 } from '../../../logger/constants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:segment-changes'); diff --git a/src/sync/polling/syncTasks/splitsSyncTask.ts b/src/sync/polling/syncTasks/splitsSyncTask.ts index 0eac3147..0b448745 100644 --- a/src/sync/polling/syncTasks/splitsSyncTask.ts +++ b/src/sync/polling/syncTasks/splitsSyncTask.ts @@ -13,7 +13,7 @@ import thenable from '../../../utils/promise/thenable'; import { ISettings } from '../../../types'; import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; -import { DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, WARN_5, INFO_10 } from '../../../logger/codesConstants'; +import { DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, WARN_5, INFO_10 } from '../../../logger/constants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:split-changes'); diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index eafc9d5f..504d658c 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -5,7 +5,7 @@ import { IPushEventEmitter } from '../types'; import { ISseEventHandler } from '../SSEClient/types'; import { INotificationError } from './types'; import { ILogger } from '../../../logger/types'; -import { WARN_6, ERROR_9, WARN_7, DEBUG_46 } from '../../../logger/codesConstants'; +import { WARN_6, ERROR_9, WARN_7, DEBUG_46 } from '../../../logger/constants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-sync:sse-handler'); diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index accdb7f4..f10c61fe 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -18,7 +18,7 @@ import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { MY_SEGMENTS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP } from './constants'; import { IPlatform } from '../../sdkFactory/types'; -import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/codesConstants'; +import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:push-manager'); diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index 2a19ccce..2eb32446 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -17,7 +17,7 @@ import { IFetchAuth } from '../../services/types'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { IPlatform } from '../../sdkFactory/types'; -import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/codesConstants'; +import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:push-manager'); diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index ca8e2649..7aba9914 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -14,7 +14,7 @@ import { authenticateFactory } from './AuthClient'; import SSEClient from './SSEClient'; import { ISettings } from '../../types'; import { IPlatform } from '../../sdkFactory/types'; -import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/codesConstants'; +import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:push-manager'); diff --git a/src/sync/submitters/eventsSyncTask.ts b/src/sync/submitters/eventsSyncTask.ts index 4895f14a..c4f74648 100644 --- a/src/sync/submitters/eventsSyncTask.ts +++ b/src/sync/submitters/eventsSyncTask.ts @@ -3,7 +3,7 @@ import { IPostEventsBulk } from '../../services/types'; import { ISyncTask, ITimeTracker } from '../types'; import { submitterSyncTaskFactory } from './submitterSyncTask'; import { ILogger } from '../../logger/types'; -import { INFO_16 } from '../../logger/codesConstants'; +import { INFO_16 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:submitters'); diff --git a/src/sync/submitters/submitterSyncTask.ts b/src/sync/submitters/submitterSyncTask.ts index 02fdfc4e..b025cbf3 100644 --- a/src/sync/submitters/submitterSyncTask.ts +++ b/src/sync/submitters/submitterSyncTask.ts @@ -2,7 +2,7 @@ import syncTaskFactory from '../syncTask'; import { ISyncTask, ITimeTracker } from '../types'; import { IRecorderCacheConsumerSync } from '../../storages/types'; import { ILogger } from '../../logger/types'; -import { INFO_17, WARN_9, WARN_10 } from '../../logger/codesConstants'; +import { INFO_17, WARN_9, WARN_10 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-sync:submitters'); diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index e5dee1eb..6831e4bd 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -8,7 +8,7 @@ import { IStorageSync } from '../storages/types'; import { IPushManagerFactoryParams, IPushManager, IPushManagerCS } from './streaming/types'; import { IPollingManager, IPollingManagerCS, IPollingManagerFactoryParams } from './polling/types'; import { PUSH_SUBSYSTEM_UP, PUSH_SUBSYSTEM_DOWN } from './streaming/constants'; -import { INFO_18, INFO_19, INFO_20 } from '../logger/codesConstants'; +import { INFO_18, INFO_19, INFO_20 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // export const log = logFactory('splitio-sync:sync-manager'); diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index c064930e..2e2d1fd1 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -1,4 +1,4 @@ -import { DEBUG_48, DEBUG_47, DEBUG_49 } from '../logger/codesConstants'; +import { DEBUG_48, DEBUG_47, DEBUG_49 } from '../logger/constants'; import { ILogger } from '../logger/types'; import { ISyncTask } from './types'; // import { logFactory } from '../logger/sdkLogger'; diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index 4397ea68..9f1dad67 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -4,7 +4,7 @@ import { IEventsCacheBase } from '../storages/types'; import { IEventsHandler, IEventTracker } from './types'; import { SplitIO } from '../types'; import { ILogger } from '../logger/types'; -import { INFO_21, WARN_11 } from '../logger/codesConstants'; +import { INFO_21, WARN_11 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client:event-tracker'); diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index 217c947b..ede9b865 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -7,7 +7,7 @@ import { IMetadata } from '../dtos/types'; import { SplitIO, ImpressionDTO } from '../types'; import { IImpressionObserver } from './impressionObserver/types'; import { ILogger } from '../logger/types'; -import { DEBUG_50, ERROR_11, ERROR_12 } from '../logger/codesConstants'; +import { DEBUG_50, ERROR_11, ERROR_12 } from '../logger/constants'; // import { logFactory } from '../logger/sdkLogger'; // const log = logFactory('splitio-client:impressions-tracker'); diff --git a/src/utils/inputValidation/attributes.ts b/src/utils/inputValidation/attributes.ts index 005a14e0..45fe4405 100644 --- a/src/utils/inputValidation/attributes.ts +++ b/src/utils/inputValidation/attributes.ts @@ -1,7 +1,7 @@ import { isObject } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { ERROR_13 } from '../../logger/codesConstants'; +import { ERROR_13 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); diff --git a/src/utils/inputValidation/event.ts b/src/utils/inputValidation/event.ts index e8e6e7ad..a5d3daff 100644 --- a/src/utils/inputValidation/event.ts +++ b/src/utils/inputValidation/event.ts @@ -1,4 +1,4 @@ -import { ERROR_14, ERROR_15, ERROR_16, ERROR_17 } from '../../logger/codesConstants'; +import { ERROR_14, ERROR_15, ERROR_16, ERROR_17 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; diff --git a/src/utils/inputValidation/eventProperties.ts b/src/utils/inputValidation/eventProperties.ts index 15912cc8..caca4be5 100644 --- a/src/utils/inputValidation/eventProperties.ts +++ b/src/utils/inputValidation/eventProperties.ts @@ -1,7 +1,7 @@ import { isObject, shallowClone, isString, isFiniteNumber, isBoolean } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { ERROR_18, ERROR_19, WARN_12, WARN_13 } from '../../logger/codesConstants'; +import { ERROR_18, ERROR_19, WARN_12, WARN_13 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); diff --git a/src/utils/inputValidation/eventValue.ts b/src/utils/inputValidation/eventValue.ts index 3653ecd3..6d0a4f38 100644 --- a/src/utils/inputValidation/eventValue.ts +++ b/src/utils/inputValidation/eventValue.ts @@ -1,4 +1,4 @@ -import { ERROR_20 } from '../../logger/codesConstants'; +import { ERROR_20 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isFiniteNumber } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index ebdfd80a..6aa2db6d 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -1,4 +1,4 @@ -import { ERROR_21, WARN_14 } from '../../logger/codesConstants'; +import { ERROR_21, WARN_14 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { IReadinessManager } from '../../readiness/types'; // import { logFactory } from '../../logger/sdkLogger'; diff --git a/src/utils/inputValidation/key.ts b/src/utils/inputValidation/key.ts index 0473ac83..66be37cb 100644 --- a/src/utils/inputValidation/key.ts +++ b/src/utils/inputValidation/key.ts @@ -1,7 +1,7 @@ import { isObject, isString, isFiniteNumber, toString } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { ERROR_22, WARN_15, ERROR_25, ERROR_23, ERROR_24, ERROR_26 } from '../../logger/codesConstants'; +import { ERROR_22, WARN_15, ERROR_25, ERROR_23, ERROR_24, ERROR_26 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); diff --git a/src/utils/inputValidation/split.ts b/src/utils/inputValidation/split.ts index 8286c2da..43b83154 100644 --- a/src/utils/inputValidation/split.ts +++ b/src/utils/inputValidation/split.ts @@ -1,4 +1,4 @@ -import { ERROR_22, ERROR_32, WARN_17, ERROR_33 } from '../../logger/codesConstants'; +import { ERROR_22, ERROR_32, WARN_17, ERROR_33 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; diff --git a/src/utils/inputValidation/splitExistance.ts b/src/utils/inputValidation/splitExistance.ts index c07f2194..f31f0bf9 100644 --- a/src/utils/inputValidation/splitExistance.ts +++ b/src/utils/inputValidation/splitExistance.ts @@ -1,7 +1,7 @@ import { SPLIT_NOT_FOUND } from '../labels'; import { IReadinessManager } from '../../readiness/types'; import { ILogger } from '../../logger/types'; -import { WARN_18 } from '../../logger/codesConstants'; +import { WARN_18 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); diff --git a/src/utils/inputValidation/splits.ts b/src/utils/inputValidation/splits.ts index 3e5fb52b..71de7998 100644 --- a/src/utils/inputValidation/splits.ts +++ b/src/utils/inputValidation/splits.ts @@ -1,4 +1,4 @@ -import { ERROR_34 } from '../../logger/codesConstants'; +import { ERROR_34 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { uniq } from '../lang'; import { validateSplit } from './split'; diff --git a/src/utils/inputValidation/trafficType.ts b/src/utils/inputValidation/trafficType.ts index 3216925e..53386610 100644 --- a/src/utils/inputValidation/trafficType.ts +++ b/src/utils/inputValidation/trafficType.ts @@ -1,4 +1,4 @@ -import { ERROR_35, ERROR_36, ERROR_37, WARN_19 } from '../../logger/codesConstants'; +import { ERROR_35, ERROR_36, ERROR_37, WARN_19 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; diff --git a/src/utils/inputValidation/trafficTypeExistance.ts b/src/utils/inputValidation/trafficTypeExistance.ts index 7baafa20..6b6088da 100644 --- a/src/utils/inputValidation/trafficTypeExistance.ts +++ b/src/utils/inputValidation/trafficTypeExistance.ts @@ -5,7 +5,7 @@ import { IReadinessManager } from '../../readiness/types'; import { SDKMode } from '../../types'; import { MaybeThenable } from '../../dtos/types'; import { ILogger } from '../../logger/types'; -import { WARN_20 } from '../../logger/codesConstants'; +import { WARN_20 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); diff --git a/src/utils/settingsValidation/impressionsMode.ts b/src/utils/settingsValidation/impressionsMode.ts index 68febe28..0b418011 100644 --- a/src/utils/settingsValidation/impressionsMode.ts +++ b/src/utils/settingsValidation/impressionsMode.ts @@ -1,4 +1,4 @@ -import { ERROR_38 } from '../../logger/codesConstants'; +import { ERROR_38 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { SplitIO } from '../../types'; import { DEBUG, OPTIMIZED } from '../constants'; diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index 93d0ea3b..7c04ed4f 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -1,4 +1,4 @@ -import { WARN_21 } from '../../../logger/codesConstants'; +import { WARN_21 } from '../../../logger/constants'; import { ILogger } from '../../../logger/types'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-settings'); diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index 793267c0..7ff0b872 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -3,7 +3,7 @@ import { validateSplits } from '../inputValidation/splits'; import { ISplitFiltersValidation } from '../../dtos/types'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { WARN_22, WARN_24, WARN_23, DEBUG_51 } from '../../logger/codesConstants'; +import { WARN_22, WARN_24, WARN_23, DEBUG_51 } from '../../logger/constants'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index a52b07ea..c4ca9aa3 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -1,7 +1,7 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS'; import { ISettings } from '../../../types'; import { ILogger } from '../../../logger/types'; -import { WARN_25 } from '../../../logger/codesConstants'; +import { WARN_25 } from '../../../logger/constants'; // import { logFactory } from '../../../logger/sdkLogger'; // const log = logFactory('splitio-settings'); From 104491142a86fa114b78a2d6556b7d0c44095e15 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 10 Mar 2021 20:09:45 -0300 Subject: [PATCH 26/58] polishing --- src/integrations/ga/SplitToGa.ts | 6 ++++-- src/logger/constants.ts | 6 +++++- src/logger/index.ts | 2 +- src/utils/inputValidation/apiKey.ts | 15 ++++++--------- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index d49cb12a..92e93365 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -8,6 +8,8 @@ import { ILogger } from '../../logger/types'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory('splitio-split-to-ga'); +const noGaWarning = '`ga` command queue not found.'; + export default class SplitToGa implements IIntegration { // A falsy object represents the default tracker @@ -88,7 +90,7 @@ export default class SplitToGa implements IIntegration { } log.info('Started Split-to-GA integration'); - if (typeof SplitToGa.getGa() !== 'function') log.warn('`ga` command queue not found. No hits will be sent until it is available.'); + if (typeof SplitToGa.getGa() !== 'function') log.warn(`${noGaWarning} No hits will be sent until it is available.`); } queue(data: SplitIO.IntegrationData) { @@ -126,7 +128,7 @@ export default class SplitToGa implements IIntegration { ga(sendCommand, fieldsObject); }); } else { - this.log.warn('`ga` command queue not found. No hit was sent.'); + this.log.warn(`${noGaWarning} No hit was sent.`); } } diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 76b311ba..eecf9f1c 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -56,7 +56,7 @@ export const DEBUG_35 = 'splitio-offline:splits-fetcher => Ignoring line since i export const DEBUG_37 = 'splitio-sync:polling-manager => Splits will be refreshed each %s millis'; // @TODO remove since we already log it in syncTask debug log? export const DEBUG_38 = 'splitio-sync:polling-manager => Segments will be refreshed each %s millis'; // @TODO remove since we already log it in syncTask debug log? - +// commons export const ERROR_0 = 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'; export const ERROR_2 = 'splitio-utils:logger => Invalid Log Level - No changes to the logs will be applied.'; export const ERROR_3 = 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'; @@ -89,12 +89,14 @@ export const ERROR_36 = '%s: you passed an invalid traffic_type_name, traffic_ty export const ERROR_37 = '%s: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.'; export const ERROR_38 = 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: \'%s\' or \'%s\'. Defaulting to \'%s\' mode.'; export const ERROR_39 = 'Response status is not OK. Status: %s. URL: %s. Message: %s'; +export const ERROR_API_KEY = 'Factory instantiation: %s, api_key must be a non-empty string'; // node export const ERROR_1 = 'splitio-client:cleanup => Error with Split graceful shutdown: %s'; export const ERROR_8 = 'splitio-sync:segment-changes => Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'; export const ERROR_6 = 'splitio-offline:splits-fetcher => Ignoring entry on YAML since the format is incorrect.'; +// commons export const INFO_0 = 'Split SDK is ready from cache.'; export const INFO_1 = 'Split SDK is ready.'; export const INFO_2 = 'splitio-client => Split: %s. Key: %s. Evaluation: %s. Label: %s'; @@ -118,6 +120,7 @@ export const INFO_19 = 'splitio-sync:sync-manager => Streaming couldn\'t connect export const INFO_20 = 'splitio-sync:sync-manager => PUSH (re)connected. Syncing and stopping periodic fetch of data.'; export const INFO_21 = 'splitio-client:event-tracker => Successfully qeued %s'; +// commons export const WARN_0 = 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'; export const WARN_1 = 'splitio-engine:value => Defined attribute [%s], no attributes received.'; export const WARN_2 = 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'; @@ -142,6 +145,7 @@ export const WARN_22 = 'Factory instantiation: split filters have been configure export const WARN_23 = 'Factory instantiation: split filter at position \'%s\' is invalid. It must be an object with a valid filter type (\'byName\' or \'byPrefix\') and a list of \'values\'.'; export const WARN_24 = 'Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'; export const WARN_25 = 'splitio-settings => The provided storage is invalid. Fallbacking into default MEMORY storage'; +export const WARN_API_KEY = 'Factory instantiation: %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'; // node export const WARN_3 = 'splitio-offline:splits-fetcher => .split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'; diff --git a/src/logger/index.ts b/src/logger/index.ts index eb3e2de4..5513fb39 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -30,7 +30,7 @@ const defaultOptions = { export class Logger implements ILogger { private category: string; - public options: Required; + private options: Required; constructor(category: string, options?: ILoggerOptions) { this.category = category; diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index ec179426..377058cb 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -1,22 +1,21 @@ +import { ERROR_API_KEY, WARN_API_KEY } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; // import { logFactory } from '../../logger/sdkLogger'; // const log = logFactory(''); -function apiKeyError(reason: string) { return `Factory instantiation: ${reason}, api_key must be a non-empty string.`; } - /** validates the given api key */ export function validateApiKey(log: ILogger, maybeApiKey: any): string | false { let apiKey: string | false = false; if (maybeApiKey == undefined) { // eslint-disable-line eqeqeq - log.error(apiKeyError('you passed a null or undefined api_key')); + log.error(ERROR_API_KEY, ['you passed a null or undefined api_key']); } else if (isString(maybeApiKey)) { if (maybeApiKey.length > 0) apiKey = maybeApiKey; else - log.error(apiKeyError('you passed an empty api_key')); + log.error(ERROR_API_KEY, ['you passed an empty api_key']); } else { - log.error(apiKeyError('you passed an invalid api_key')); + log.error(ERROR_API_KEY, ['you passed an invalid api_key']); } return apiKey; @@ -24,8 +23,6 @@ export function validateApiKey(log: ILogger, maybeApiKey: any): string | false { const usedKeysMap: Record = {}; -function apiKeyWarn(reason: string) { return `Factory instantiation: ${reason}. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.`; } - /** validates the given api key and also warns if it is in use */ export function validateAndTrackApiKey(log: ILogger, maybeApiKey: any): string | false { const apiKey = validateApiKey(log, maybeApiKey); @@ -36,10 +33,10 @@ export function validateAndTrackApiKey(log: ILogger, maybeApiKey: any): string | // If this key is not present, only warning scenarios is that we have factories for other keys. usedKeysMap[apiKey] = 1; if (Object.keys(usedKeysMap).length > 1) { - log.warn(apiKeyWarn('You already have an instance of the Split factory. Make sure you definitely want this additional instance')); + log.warn(WARN_API_KEY, ['You already have an instance of the Split factory. Make sure you definitely want this additional instance']); } } else { - log.warn(apiKeyWarn(`You already have ${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key`)); + log.warn(WARN_API_KEY, [`You already have ${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key`]); usedKeysMap[apiKey]++; } } From 94379503ed9736b4be3a80f121f19bfd1f894718 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 11 Mar 2021 15:31:50 -0300 Subject: [PATCH 27/58] feedback --- src/utils/settingsValidation/index.ts | 14 +++++++------- src/utils/timeTracker/index.ts | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/utils/settingsValidation/index.ts b/src/utils/settingsValidation/index.ts index b756a65c..b3302b35 100644 --- a/src/utils/settingsValidation/index.ts +++ b/src/utils/settingsValidation/index.ts @@ -112,7 +112,7 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV const withDefaults = merge({}, base, defaults, config) as ISettingsInternal; // ensure a valid logger - const log = logFactory('splitio'); // @ts-ignore + const log = logFactory('splitio'); // @ts-ignore, modify readonly prop withDefaults.log = log; // Scheduler periods @@ -129,11 +129,11 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV withDefaults.startup.eventsFirstPushWindow = fromSecondsToMillis(withDefaults.startup.eventsFirstPushWindow); // ensure a valid SDK mode - // @ts-ignore + // @ts-ignore, modify readonly prop withDefaults.mode = mode(withDefaults.core.authorizationKey, withDefaults.mode); // ensure a valid Storage based on mode defined. - // @ts-ignore + // @ts-ignore, modify readonly prop if (storage) withDefaults.storage = storage(withDefaults); setupLogger(withDefaults.debug); @@ -144,16 +144,16 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV } // Current ip/hostname information - // @ts-ignore + // @ts-ignore, modify readonly prop withDefaults.runtime = runtime(withDefaults); // ensure a valid list of integrations. // `integrations` returns an array of valid integration items. - // @ts-ignore + // @ts-ignore, modify readonly prop if (integrations) withDefaults.integrations = integrations(withDefaults); // validate push options - if (withDefaults.streamingEnabled !== false) { // @ts-ignore + if (withDefaults.streamingEnabled !== false) { // @ts-ignore, modify readonly prop withDefaults.streamingEnabled = true; // Backoff bases. // We are not checking if bases are positive numbers. Thus, we might be reauthenticating immediately (`setTimeout` with NaN or negative number) @@ -162,7 +162,7 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV // validate the `splitFilters` settings and parse splits query const splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters, withDefaults.mode); - withDefaults.sync.splitFilters = splitFiltersValidation.validFilters; // @ts-ignore + withDefaults.sync.splitFilters = splitFiltersValidation.validFilters; withDefaults.sync.__splitFiltersValidation = splitFiltersValidation; // ensure a valid impressionsMode diff --git a/src/utils/timeTracker/index.ts b/src/utils/timeTracker/index.ts index 329dc707..27dd3896 100644 --- a/src/utils/timeTracker/index.ts +++ b/src/utils/timeTracker/index.ts @@ -203,7 +203,7 @@ const TrackerAPI = { if (timerData) { // Stop the timer and round result for readability. const et = timerData.timer(); - log.debug(`time tracker: [${task}] took ${et}ms to finish.`); + log.debug(`[TIME TRACKER]: [${task}] took ${et}ms to finish.`); // Check if we have a tracker callback. if (timerData.cb) { From 453e82ce528fbf3517a4f2141c98a19bda3df032 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 11 Mar 2021 17:16:20 -0300 Subject: [PATCH 28/58] polishing on tests --- .../ga/__tests__/SplitToGa.spec.ts | 4 +- src/logger/__tests__/sdkLogger.mock.ts | 14 +- .../__tests__/sdkReadinessManager.spec.ts | 8 +- .../inRedis/__tests__/RedisAdapter.spec.ts | 544 +++++++++--------- .../inputValidation/__tests__/apiKey.spec.ts | 18 +- .../__tests__/attributes.spec.ts | 10 +- .../inputValidation/__tests__/event.spec.ts | 8 +- .../__tests__/eventProperties.spec.ts | 18 +- .../__tests__/eventValue.spec.ts | 10 +- .../__tests__/isOperational.spec.ts | 14 +- .../inputValidation/__tests__/key.spec.ts | 20 +- .../inputValidation/__tests__/split.spec.ts | 10 +- .../__tests__/splitExistance.spec.ts | 6 +- .../inputValidation/__tests__/splits.spec.ts | 4 +- .../__tests__/trafficType.spec.ts | 10 +- .../__tests__/trafficTypeExistance.spec.ts | 18 +- .../__tests__/splitFilters.spec.ts | 10 +- 17 files changed, 332 insertions(+), 394 deletions(-) diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index cf6100c6..04b0ccdf 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -2,7 +2,7 @@ import { SplitIO } from '../../../types'; import { SPLIT_IMPRESSION, SPLIT_EVENT } from '../../../utils/constants'; // Mocks -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { gaMock, gaRemove } from './gaMock'; // Test target @@ -79,7 +79,7 @@ describe('SplitToGa', () => { }); test('SplitToGa.getGa', () => { - mockClear(); + loggerMock.mockClear(); const { ga } = gaMock(); expect(SplitToGa.getGa()).toBe(ga); // should return ga command queue if it exists diff --git a/src/logger/__tests__/sdkLogger.mock.ts b/src/logger/__tests__/sdkLogger.mock.ts index 542c6b35..2e4c045e 100644 --- a/src/logger/__tests__/sdkLogger.mock.ts +++ b/src/logger/__tests__/sdkLogger.mock.ts @@ -3,11 +3,11 @@ export const loggerMock = { error: jest.fn(), debug: jest.fn(), info: jest.fn(), -}; -export function mockClear() { - loggerMock.warn.mockClear(); - loggerMock.error.mockClear(); - loggerMock.debug.mockClear(); - loggerMock.info.mockClear(); -} + mockClear() { + this.warn.mockClear(); + this.error.mockClear(); + this.debug.mockClear(); + this.info.mockClear(); + } +}; diff --git a/src/readiness/__tests__/sdkReadinessManager.spec.ts b/src/readiness/__tests__/sdkReadinessManager.spec.ts index d148b1fa..7034592c 100644 --- a/src/readiness/__tests__/sdkReadinessManager.spec.ts +++ b/src/readiness/__tests__/sdkReadinessManager.spec.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import { loggerMock, mockClear } from '../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../logger/__tests__/sdkLogger.mock'; import { IEventEmitter } from '../../types'; import { SDK_READY, SDK_READY_FROM_CACHE, SDK_READY_TIMED_OUT, SDK_UPDATE } from '../constants'; import sdkReadinessManagerFactory from '../sdkReadinessManager'; @@ -34,9 +34,7 @@ function emitTimeoutEvent(readinessManager: IReadinessManager) { describe('SDK Readiness Manager - Event emitter', () => { - afterEach(() => { - mockClear(); - }); + afterEach(() => { loggerMock.mockClear(); }); test('Providing the gate object to get the SDK status interface that manages events', () => { expect(typeof sdkReadinessManagerFactory).toBe('function'); // The module exposes a function. @@ -256,7 +254,7 @@ describe('SDK Readiness Manager - Ready promise', () => { await ready.then( () => { expect('It should be a resolved promise when the SDK is ready, even after an SDK timeout.'); - mockClear(); + loggerMock.mockClear(); testPassedCount++; expect(testPassedCount).toBe(5); done(); diff --git a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts index 4fd3e599..93c4bdb1 100644 --- a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts +++ b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts @@ -5,7 +5,7 @@ import reduce from 'lodash/reduce'; import { _Set, setToArray } from '../../../utils/lang/sets'; // Mocking sdkLogger -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; // Mocking ioredis @@ -55,336 +55,334 @@ import timeout from '../../../utils/promise/timeout'; import RedisAdapter from '../RedisAdapter'; function clearAllMocks() { - mockClear(); // clear logger mocks + loggerMock.mockClear(); ioredisMock.once.mockClear(); } -/** - * Logs here won't be changing much, so we could validate those. It's not important the exact message but what do they represent. - */ -test('STORAGE Redis Adapter / Class', () => { - expect(Object.getPrototypeOf(RedisAdapter)).toBe(ioredis); // The returned class extends from the library of choice (ioredis). +describe('STORAGE Redis Adapter', () => { - const instance = new RedisAdapter(loggerMock, { - url: 'redis://localhost:6379/0', - connectionTimeout: 10000, - operationTimeout: 10000 - }); + afterEach(clearAllMocks); - expect(instance instanceof RedisAdapter).toBe(true); // Of course created instance should be an instance of the adapter. - expect(instance instanceof ioredis).toBe(true); // And as the class extends from the library, the instance is an instance of the library as well. + /** + * Logs here won't be changing much, so we could validate those. It's not important the exact message but what do they represent. + */ + test('Class', () => { + expect(Object.getPrototypeOf(RedisAdapter)).toBe(ioredis); // The returned class extends from the library of choice (ioredis). - expect(typeof instance._options === 'object').toBe(true); // The instance will have an options object. - expect(Array.isArray(instance._notReadyCommandsQueue)).toBe(true); // The instance will have an array as the _notReadyCommandsQueue property. - expect(instance._runningCommands instanceof _Set).toBe(true); // The instance will have a set as the _runningCommands property. -}); + const instance = new RedisAdapter(loggerMock, { + url: 'redis://localhost:6379/0', + connectionTimeout: 10000, + operationTimeout: 10000 + }); -test('STORAGE Redis Adapter / ioredis constructor params and static method _defineLibrarySettings', () => { - const redisUrl = 'redis://localhost:6379/0'; - const redisParams = { - host: 'fake_host', port: '6355', 'db': 5, pass: 'fake_pass' - }; + expect(instance instanceof RedisAdapter).toBe(true); // Of course created instance should be an instance of the adapter. + expect(instance instanceof ioredis).toBe(true); // And as the class extends from the library, the instance is an instance of the library as well. - new RedisAdapter(loggerMock, { - url: redisUrl, - connectionTimeout: 123, - operationTimeout: 124 - }); - // Keep in mind we're storing the arguments object, not a true array. - expect(constructorParams.length).toBe(2); // In this signature, the constructor receives two params. - expect(constructorParams[0]).toBe(redisUrl); // When we use the Redis URL, that should be the first parameter passed to ioredis constructor - expect(constructorParams[1]).toEqual({ enableOfflineQueue: false, connectTimeout: 10000, lazyConnect: false }); // and the second parameter would be the default settings for the lib. - - new RedisAdapter(loggerMock, { - ...redisParams, - connectionTimeout: 123, - operationTimeout: 124 + expect(typeof instance._options === 'object').toBe(true); // The instance will have an options object. + expect(Array.isArray(instance._notReadyCommandsQueue)).toBe(true); // The instance will have an array as the _notReadyCommandsQueue property. + expect(instance._runningCommands instanceof _Set).toBe(true); // The instance will have a set as the _runningCommands property. }); - expect(constructorParams.length).toBe(1); // In this signature, the constructor receives one param. - // we keep "pass" instead of "password" on our settings API to be backwards compatible. - expect(constructorParams[0]).toEqual({ host: redisParams.host, port: redisParams.port, db: redisParams.db, password: redisParams.pass, enableOfflineQueue: false, connectTimeout: 10000, lazyConnect: false }); // If we send all the redis params separate, it will pass one object to the library containing that and the rest of the options. - - new RedisAdapter(loggerMock, { - ...redisParams, - url: redisUrl, - connectionTimeout: 123, - operationTimeout: 124 + test('ioredis constructor params and static method _defineLibrarySettings', () => { + const redisUrl = 'redis://localhost:6379/0'; + const redisParams = { + host: 'fake_host', port: '6355', 'db': 5, pass: 'fake_pass' + }; + + new RedisAdapter(loggerMock, { + url: redisUrl, + connectionTimeout: 123, + operationTimeout: 124 + }); + // Keep in mind we're storing the arguments object, not a true array. + expect(constructorParams.length).toBe(2); // In this signature, the constructor receives two params. + expect(constructorParams[0]).toBe(redisUrl); // When we use the Redis URL, that should be the first parameter passed to ioredis constructor + expect(constructorParams[1]).toEqual({ enableOfflineQueue: false, connectTimeout: 10000, lazyConnect: false }); // and the second parameter would be the default settings for the lib. + + new RedisAdapter(loggerMock, { + ...redisParams, + connectionTimeout: 123, + operationTimeout: 124 + }); + + expect(constructorParams.length).toBe(1); // In this signature, the constructor receives one param. + // we keep "pass" instead of "password" on our settings API to be backwards compatible. + expect(constructorParams[0]).toEqual({ host: redisParams.host, port: redisParams.port, db: redisParams.db, password: redisParams.pass, enableOfflineQueue: false, connectTimeout: 10000, lazyConnect: false }); // If we send all the redis params separate, it will pass one object to the library containing that and the rest of the options. + + new RedisAdapter(loggerMock, { + ...redisParams, + url: redisUrl, + connectionTimeout: 123, + operationTimeout: 124 + }); + + expect(constructorParams.length).toBe(2); // In this signature, the constructor receives two params. + expect(constructorParams[0]).toBe(redisUrl); // When we use the Redis URL, even if we specified all the other params one by one the URL takes precedence, so that should be the first parameter passed to ioredis constructor + expect(constructorParams[1]).toEqual({ enableOfflineQueue: false, connectTimeout: 10000, lazyConnect: false }); // and the second parameter would be the default settings for the lib. }); - expect(constructorParams.length).toBe(2); // In this signature, the constructor receives two params. - expect(constructorParams[0]).toBe(redisUrl); // When we use the Redis URL, even if we specified all the other params one by one the URL takes precedence, so that should be the first parameter passed to ioredis constructor - expect(constructorParams[1]).toEqual({ enableOfflineQueue: false, connectTimeout: 10000, lazyConnect: false }); // and the second parameter would be the default settings for the lib. -}); - -test('STORAGE Redis Adapter / static method - _defineOptions', () => { - const defaultOptions = { - connectionTimeout: 10000, - operationTimeout: 5000 - }; - - expect(RedisAdapter._defineOptions({})).toEqual(defaultOptions); // We get the default options if we use an empty object. - - expect(RedisAdapter._defineOptions({ - url: 'redis_url' - })).toEqual({ - connectionTimeout: 10000, - operationTimeout: 5000, - url: 'redis_url' - }); // We get the merge of the provided and the default options. - - const opts = { - host: 'host', port: 'port', db: 'db', pass: 'pass' - }; - - expect(RedisAdapter._defineOptions(opts)).not.toEqual(opts); // Provided options are not mutated. - expect(opts).toEqual({ host: 'host', port: 'port', db: 'db', pass: 'pass' }); // Provided options are not mutated. - - expect(RedisAdapter._defineOptions(opts)).toEqual(merge({}, defaultOptions, opts)); // We get the merge of the provided and the default options. - - expect(RedisAdapter._defineOptions({ - random: 1, - crap: 'I do not think I can make it', - secret: 'shh', - url: 'I will make it' - })).toEqual(merge({}, defaultOptions, { url: 'I will make it' })); // Unwanted options will be skipped. -}); - -test('STORAGE Redis Adapter / instance methods - _listenToEvents', (done) => { - // Reset all stubs - clearAllMocks(); - - expect(ioredisMock.once.mock.calls.length).toBe(0); // Control assertion - expect(ioredisMock[METHODS_TO_PROMISE_WRAP[0]].mock.calls.length).toBe(0); // Control assertion - - const instance = new RedisAdapter(loggerMock, { - url: 'redis://localhost:6379/0' + test('static method - _defineOptions', () => { + const defaultOptions = { + connectionTimeout: 10000, + operationTimeout: 5000 + }; + + expect(RedisAdapter._defineOptions({})).toEqual(defaultOptions); // We get the default options if we use an empty object. + + expect(RedisAdapter._defineOptions({ + url: 'redis_url' + })).toEqual({ + connectionTimeout: 10000, + operationTimeout: 5000, + url: 'redis_url' + }); // We get the merge of the provided and the default options. + + const opts = { + host: 'host', port: 'port', db: 'db', pass: 'pass' + }; + + expect(RedisAdapter._defineOptions(opts)).not.toEqual(opts); // Provided options are not mutated. + expect(opts).toEqual({ host: 'host', port: 'port', db: 'db', pass: 'pass' }); // Provided options are not mutated. + + expect(RedisAdapter._defineOptions(opts)).toEqual(merge({}, defaultOptions, opts)); // We get the merge of the provided and the default options. + + expect(RedisAdapter._defineOptions({ + random: 1, + crap: 'I do not think I can make it', + secret: 'shh', + url: 'I will make it' + })).toEqual(merge({}, defaultOptions, { url: 'I will make it' })); // Unwanted options will be skipped. }); - expect(ioredisMock.once.mock.calls.length).toBe(2); // If the method was called, it should have called the `once` function twice. If that it the case we can assume that the method was called on creation. + test('instance methods - _listenToEvents', (done) => { + expect(ioredisMock.once.mock.calls.length).toBe(0); // Control assertion + expect(ioredisMock[METHODS_TO_PROMISE_WRAP[0]].mock.calls.length).toBe(0); // Control assertion - // Reset stubs again, we'll check the behaviour calling the method directly. - clearAllMocks(); - expect(ioredisMock.once.mock.calls.length).toBe(0); // Control assertion - expect(ioredisMock[METHODS_TO_PROMISE_WRAP[METHODS_TO_PROMISE_WRAP.length - 1]].mock.calls.length).toBe(0); // Control assertion + const instance = new RedisAdapter(loggerMock, { + url: 'redis://localhost:6379/0' + }); - instance._listenToEvents(); + expect(ioredisMock.once.mock.calls.length).toBe(2); // If the method was called, it should have called the `once` function twice. If that it the case we can assume that the method was called on creation. - expect(ioredisMock.once.mock.calls.length).toBe(2); // The "once" method of the instance should be called twice. + // Reset stubs again, we'll check the behaviour calling the method directly. + clearAllMocks(); + expect(ioredisMock.once.mock.calls.length).toBe(0); // Control assertion + expect(ioredisMock[METHODS_TO_PROMISE_WRAP[METHODS_TO_PROMISE_WRAP.length - 1]].mock.calls.length).toBe(0); // Control assertion - const firstCallArgs = ioredisMock.once.mock.calls[0]; + instance._listenToEvents(); - expect(firstCallArgs[0]).toBe('ready'); // First argument for the first call should be the "ready" event. - expect(typeof firstCallArgs[1]).toBe('function'); // second argument for the first call should be a callback function. + expect(ioredisMock.once.mock.calls.length).toBe(2); // The "once" method of the instance should be called twice. - const secondCallArgs = ioredisMock.once.mock.calls[1]; + const firstCallArgs = ioredisMock.once.mock.calls[0]; - expect(secondCallArgs[0]).toBe('close'); // First argument for the first call should be the "close" event. - expect(typeof secondCallArgs[1]).toBe('function'); // second argument for the first call should be a callback function. + expect(firstCallArgs[0]).toBe('ready'); // First argument for the first call should be the "ready" event. + expect(typeof firstCallArgs[1]).toBe('function'); // second argument for the first call should be a callback function. - expect(loggerMock.warn.mock.calls.length).toBe(0); // Control assertion - secondCallArgs[1](); // Execute the callback for "close" + const secondCallArgs = ioredisMock.once.mock.calls[1]; - expect(loggerMock.info.mock.calls.length).toBe(1); // The callback for the "close" event will only log info to the user about what is going on. - expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection closed.']); // The callback for the "close" event will only log info to the user about what is going on. + expect(secondCallArgs[0]).toBe('close'); // First argument for the first call should be the "close" event. + expect(typeof secondCallArgs[1]).toBe('function'); // second argument for the first call should be a callback function. - loggerMock.info.mockClear(); - expect(loggerMock.info.mock.calls.length).toBe(0); // Control assertion - expect(Array.isArray(instance._notReadyCommandsQueue)).toBe(true); // Control assertion + expect(loggerMock.warn.mock.calls.length).toBe(0); // Control assertion + secondCallArgs[1](); // Execute the callback for "close" - // Without any offline commands queued, execute the callback for "ready" - firstCallArgs[1](); + expect(loggerMock.info.mock.calls.length).toBe(1); // The callback for the "close" event will only log info to the user about what is going on. + expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection closed.']); // The callback for the "close" event will only log info to the user about what is going on. - expect(loggerMock.info.mock.calls.length).not.toBe(0); // The callback for the "ready" event will inform the user about the trigger. - expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection established. Queued commands: 0.']); // The callback for the "ready" event will inform the user about the trigger. - expect(instance._notReadyCommandsQueue).toBe(undefined); // After the DB is ready, it will clean up the offline commands queue so we do not queue commands anymore. + loggerMock.info.mockClear(); + expect(loggerMock.info.mock.calls.length).toBe(0); // Control assertion + expect(Array.isArray(instance._notReadyCommandsQueue)).toBe(true); // Control assertion - // Don't do this at home - const queuedGetCommand = { - command: jest.fn(() => Promise.resolve()), - name: 'GET', - resolve: jest.fn(), - reject: jest.fn() - }; - const queuedSetCommand = { - command: jest.fn(() => Promise.reject()), - name: 'SET', - resolve: jest.fn(), - reject: jest.fn() - }; - instance._notReadyCommandsQueue = [queuedGetCommand, queuedSetCommand]; - loggerMock.info.mockClear(); + // Without any offline commands queued, execute the callback for "ready" + firstCallArgs[1](); - // execute the callback for "ready" once more - firstCallArgs[1](); + expect(loggerMock.info.mock.calls.length).not.toBe(0); // The callback for the "ready" event will inform the user about the trigger. + expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection established. Queued commands: 0.']); // The callback for the "ready" event will inform the user about the trigger. + expect(instance._notReadyCommandsQueue).toBe(undefined); // After the DB is ready, it will clean up the offline commands queue so we do not queue commands anymore. - expect(loggerMock.info.mock.calls.length).toBe(3); // If we had queued commands, it will log the event (1 call) as well as each executed command (n calls). - expect(loggerMock.info.mock.calls).toEqual([ - ['Redis connection established. Queued commands: 2.'], // The callback for the "ready" event will inform the user about the trigger and the amount of queued commands. - ['Executing queued GET command.'], // If we had queued, it will log the event as well as each executed command. - ['Executing queued SET command.'] // If we had queued commands, it will log the event as well as each executed command. - ]); - expect(queuedGetCommand.command.mock.calls.length).toBe(1); // It will execute each queued command. + // Don't do this at home + const queuedGetCommand = { + command: jest.fn(() => Promise.resolve()), + name: 'GET', + resolve: jest.fn(), + reject: jest.fn() + }; + const queuedSetCommand = { + command: jest.fn(() => Promise.reject()), + name: 'SET', + resolve: jest.fn(), + reject: jest.fn() + }; + instance._notReadyCommandsQueue = [queuedGetCommand, queuedSetCommand]; + loggerMock.info.mockClear(); - setTimeout(() => { // Remember this is tied to a promise. - expect(queuedGetCommand.resolve.mock.calls.length).not.toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. - expect(queuedGetCommand.reject.mock.calls.length).toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. - expect(queuedSetCommand.reject.mock.calls.length).not.toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. - expect(queuedSetCommand.resolve.mock.calls.length).toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. + // execute the callback for "ready" once more + firstCallArgs[1](); - done(); - }, 5); -}); + expect(loggerMock.info.mock.calls.length).toBe(3); // If we had queued commands, it will log the event (1 call) as well as each executed command (n calls). + expect(loggerMock.info.mock.calls).toEqual([ + ['Redis connection established. Queued commands: 2.'], // The callback for the "ready" event will inform the user about the trigger and the amount of queued commands. + ['Executing queued GET command.'], // If we had queued, it will log the event as well as each executed command. + ['Executing queued SET command.'] // If we had queued commands, it will log the event as well as each executed command. + ]); + expect(queuedGetCommand.command.mock.calls.length).toBe(1); // It will execute each queued command. -test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queueing commands 1/2 - Error path', (done) => { - clearAllMocks(); + setTimeout(() => { // Remember this is tied to a promise. + expect(queuedGetCommand.resolve.mock.calls.length).not.toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. + expect(queuedGetCommand.reject.mock.calls.length).toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. + expect(queuedSetCommand.reject.mock.calls.length).not.toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. + expect(queuedSetCommand.resolve.mock.calls.length).toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. - const instance = new RedisAdapter(loggerMock, { - url: 'redis://localhost:6379/0' + done(); + }, 5); }); - forEach(METHODS_TO_PROMISE_WRAP, methodName => { - expect(instance[methodName]).not.toBe(ioredisMock[methodName]); // Method "${methodName}" from ioredis library should be wrapped. - expect(ioredisMock[methodName].mock.calls.length).toBe(0); // Checking that the method was not called yet. - - const startingQueueLength = instance._notReadyCommandsQueue.length; + test('instance methods - _setTimeoutWrappers and queueing commands 1/2 - Error path', (done) => { - // We do have the commands queue on this state, so a call for this methods will queue the command. - const wrapperResult = instance[methodName](methodName); - expect(wrapperResult instanceof Promise).toBe(true); // The result is a promise since we are queueing commands on this state. + const instance = new RedisAdapter(loggerMock, { + url: 'redis://localhost:6379/0' + }); - expect(instance._notReadyCommandsQueue.length).toBe(startingQueueLength + 1); // The queue should have one more item. - const queuedCommand = instance._notReadyCommandsQueue[0]; + forEach(METHODS_TO_PROMISE_WRAP, methodName => { + expect(instance[methodName]).not.toBe(ioredisMock[methodName]); // Method "${methodName}" from ioredis library should be wrapped. + expect(ioredisMock[methodName].mock.calls.length).toBe(0); // Checking that the method was not called yet. - expect(typeof queuedCommand.resolve).toBe('function'); // The queued item should have the correct form. - expect(typeof queuedCommand.reject).toBe('function'); // The queued item should have the correct form. - expect(typeof queuedCommand.command).toBe('function'); // The queued item should have the correct form. - expect(queuedCommand.name).toBe(methodName.toUpperCase()); // The queued item should have the correct form. - }); - - instance._notReadyCommandsQueue = false; // Remove the queue. - loggerMock.error.resetHistory; - - forEach(METHODS_TO_PROMISE_WRAP, (methodName, index) => { - // We do NOT have the commands queue on this state, so a call for this methods will execute the command. - expect(ioredisMock[methodName].mock.calls.length).toBe(0); // Control assertion - Original method (${methodName}) was not called yet + const startingQueueLength = instance._notReadyCommandsQueue.length; - const previousTimeoutCalls = timeout.mock.calls.length; - let previousRunningCommandsSize = instance._runningCommands.size; - instance[methodName](methodName).catch(() => { }); // Swallow exception so it's not spread to logs. - expect(ioredisMock[methodName].mock.calls.length).not.toBe(0); // Original method (${methodName}) is called right away (through wrapper) when we are not queueing anymore. - expect(instance._runningCommands.size).toBe(previousRunningCommandsSize + 1); // If the result of the operation was a thenable it will add the item to the running commands queue. + // We do have the commands queue on this state, so a call for this methods will queue the command. + const wrapperResult = instance[methodName](methodName); + expect(wrapperResult instanceof Promise).toBe(true); // The result is a promise since we are queueing commands on this state. - expect(timeout.mock.calls.length).toBe(previousTimeoutCalls + 1); // The promise returned by the original method should have a timeout wrapper. + expect(instance._notReadyCommandsQueue.length).toBe(startingQueueLength + 1); // The queue should have one more item. + const queuedCommand = instance._notReadyCommandsQueue[0]; - // Get the original promise (the one passed to timeout) - const commandTimeoutResolver = timeoutPromiseResolvers[0]; + expect(typeof queuedCommand.resolve).toBe('function'); // The queued item should have the correct form. + expect(typeof queuedCommand.reject).toBe('function'); // The queued item should have the correct form. + expect(typeof queuedCommand.command).toBe('function'); // The queued item should have the correct form. + expect(queuedCommand.name).toBe(methodName.toUpperCase()); // The queued item should have the correct form. + }); - expect(timeout.mock.calls[0]).toEqual([5000, commandTimeoutResolver.originalPromise]); // Timeout function should have received the correct ms amount and the right promise. - expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(true); // Correct promise should be the one on the _runningCommands queue. + instance._notReadyCommandsQueue = false; // Remove the queue. + loggerMock.error.resetHistory; - commandTimeoutResolver.rej('test'); - setTimeout(() => { // Allow the promises to tick. - expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes with error, it's promise is removed from the instance._runningCommands queue. - expect(loggerMock.error.mock.calls[index]).toEqual([`${methodName} operation threw an error or exceeded configured timeout of 5000ms. Message: test`]); // The log error method should be called with the corresponding messages, depending on the method, error and operationTimeout. - }, 0); - }); + forEach(METHODS_TO_PROMISE_WRAP, (methodName, index) => { + // We do NOT have the commands queue on this state, so a call for this methods will execute the command. + expect(ioredisMock[methodName].mock.calls.length).toBe(0); // Control assertion - Original method (${methodName}) was not called yet - setTimeout(() => { - done(); - }, 200); -}); + const previousTimeoutCalls = timeout.mock.calls.length; + let previousRunningCommandsSize = instance._runningCommands.size; + instance[methodName](methodName).catch(() => { }); // Swallow exception so it's not spread to logs. + expect(ioredisMock[methodName].mock.calls.length).not.toBe(0); // Original method (${methodName}) is called right away (through wrapper) when we are not queueing anymore. + expect(instance._runningCommands.size).toBe(previousRunningCommandsSize + 1); // If the result of the operation was a thenable it will add the item to the running commands queue. -test('STORAGE Redis Adapter / instance methods - _setTimeoutWrappers and queueing commands 2/2 - Success path', (done) => { - clearAllMocks(); + expect(timeout.mock.calls.length).toBe(previousTimeoutCalls + 1); // The promise returned by the original method should have a timeout wrapper. - const instance = new RedisAdapter(loggerMock, { - url: 'redis://localhost:6379/0' - }); + // Get the original promise (the one passed to timeout) + const commandTimeoutResolver = timeoutPromiseResolvers[0]; - instance._notReadyCommandsQueue = false; // Connection is "ready" + expect(timeout.mock.calls[0]).toEqual([5000, commandTimeoutResolver.originalPromise]); // Timeout function should have received the correct ms amount and the right promise. + expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(true); // Correct promise should be the one on the _runningCommands queue. - forEach(METHODS_TO_PROMISE_WRAP, methodName => { - // Just call the wrapped method, we don't care about all the paths tested on the previous case, just how it behaves when the command is resolved. - instance[methodName](methodName); - // Get the original promise (the one passed to timeout) - const commandTimeoutResolver = timeoutPromiseResolvers[0]; + commandTimeoutResolver.rej('test'); + setTimeout(() => { // Allow the promises to tick. + expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes with error, it's promise is removed from the instance._runningCommands queue. + expect(loggerMock.error.mock.calls[index]).toEqual([`${methodName} operation threw an error or exceeded configured timeout of 5000ms. Message: test`]); // The log error method should be called with the corresponding messages, depending on the method, error and operationTimeout. + }, 0); + }); - commandTimeoutResolver.res('test'); - setTimeout(() => { // Allow the promises to tick. - expect(loggerMock.error.mock.calls.length).toBe(0); // No error should be logged - expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes successfully, it's promise is removed from the instance._runningCommands queue. - }, 0); + setTimeout(() => { + done(); + }, 200); }); - setTimeout(() => { - done(); - }, 200); -}); - -test('STORAGE Redis Adapter / instance methods - _setDisconnectWrapper', (done) => { - clearAllMocks(); - - const instance = new RedisAdapter(loggerMock, { - url: 'redis://localhost:6379/0' + test('instance methods - _setTimeoutWrappers and queueing commands 2/2 - Success path', (done) => { + const instance = new RedisAdapter(loggerMock, { + url: 'redis://localhost:6379/0' + }); + + instance._notReadyCommandsQueue = false; // Connection is "ready" + + forEach(METHODS_TO_PROMISE_WRAP, methodName => { + // Just call the wrapped method, we don't care about all the paths tested on the previous case, just how it behaves when the command is resolved. + instance[methodName](methodName); + // Get the original promise (the one passed to timeout) + const commandTimeoutResolver = timeoutPromiseResolvers[0]; + + commandTimeoutResolver.res('test'); + setTimeout(() => { // Allow the promises to tick. + expect(loggerMock.error.mock.calls.length).toBe(0); // No error should be logged + expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes successfully, it's promise is removed from the instance._runningCommands queue. + }, 0); + }); + + setTimeout(() => { + done(); + }, 200); }); - expect(instance.disconnect).not.toBe(ioredisMock.disconnect); // disconnect() method from redis library should be wrapped. + test('instance methods - _setDisconnectWrapper', (done) => { + const instance = new RedisAdapter(loggerMock, { + url: 'redis://localhost:6379/0' + }); - // Call the method. - // Note that there are no commands on the queue for this first run. - instance.disconnect(); - expect(ioredisMock.disconnect.mock.calls.length).toBe(0); // Original method should not be called right away. + expect(instance.disconnect).not.toBe(ioredisMock.disconnect); // disconnect() method from redis library should be wrapped. - setTimeout(() => { // o queued commands timeout wrapper. - expect(loggerMock.debug.mock.calls).toEqual([['No commands pending execution, disconnect.']]); - expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously - loggerMock.debug.mockClear(); - ioredisMock.disconnect.mockClear(); - - // Second run, two pending commands, one will fail. - instance._runningCommands.add(Promise.resolve()); + // Call the method. + // Note that there are no commands on the queue for this first run. instance.disconnect(); - const rejectedPromise = Promise.reject('test-error'); - instance._runningCommands.add(rejectedPromise); - rejectedPromise.catch(() => { }); // Swallow the unhandled to avoid unhandledRejection warns - - setTimeout(() => { // queued with rejection timeout wrapper - expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 2 commands still waiting for resolution. Defering disconnection until those finish.']]); - - Promise.all(setToArray(instance._runningCommands)).catch(e => { - setImmediate(() => { // Allow the callback to execute before checking. - expect(loggerMock.warn.mock.calls[0]).toEqual([`Pending commands finished with error: ${e}. Proceeding with disconnection.`]); // Should warn about the error but tell user that will disconnect anyways. - expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously - - loggerMock.info.mockClear(); - loggerMock.warn.mockClear(); - ioredisMock.disconnect.mockClear(); - - // Third run, pending commands all successful - instance._runningCommands.clear(); - instance._runningCommands.add(Promise.resolve()); - instance._runningCommands.add(Promise.resolve()); - instance.disconnect(); - instance._runningCommands.add(Promise.resolve()); - instance._runningCommands.add(Promise.resolve()); - - setTimeout(() => { - expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 4 commands still waiting for resolution. Defering disconnection until those finish.']]); - - Promise.all(setToArray(instance._runningCommands)).then(() => { // This one will go through success path - setImmediate(() => { - expect(loggerMock.debug.mock.calls).toEqual([['Pending commands finished successfully, disconnecting.']]); - expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously + expect(ioredisMock.disconnect.mock.calls.length).toBe(0); // Original method should not be called right away. + + setTimeout(() => { // o queued commands timeout wrapper. + expect(loggerMock.debug.mock.calls).toEqual([['No commands pending execution, disconnect.']]); + expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously + loggerMock.debug.mockClear(); + ioredisMock.disconnect.mockClear(); + + // Second run, two pending commands, one will fail. + instance._runningCommands.add(Promise.resolve()); + instance.disconnect(); + const rejectedPromise = Promise.reject('test-error'); + instance._runningCommands.add(rejectedPromise); + rejectedPromise.catch(() => { }); // Swallow the unhandled to avoid unhandledRejection warns + + setTimeout(() => { // queued with rejection timeout wrapper + expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 2 commands still waiting for resolution. Defering disconnection until those finish.']]); + + Promise.all(setToArray(instance._runningCommands)).catch(e => { + setImmediate(() => { // Allow the callback to execute before checking. + expect(loggerMock.warn.mock.calls[0]).toEqual([`Pending commands finished with error: ${e}. Proceeding with disconnection.`]); // Should warn about the error but tell user that will disconnect anyways. + expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously + + loggerMock.info.mockClear(); + loggerMock.warn.mockClear(); + ioredisMock.disconnect.mockClear(); + + // Third run, pending commands all successful + instance._runningCommands.clear(); + instance._runningCommands.add(Promise.resolve()); + instance._runningCommands.add(Promise.resolve()); + instance.disconnect(); + instance._runningCommands.add(Promise.resolve()); + instance._runningCommands.add(Promise.resolve()); + + setTimeout(() => { + expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 4 commands still waiting for resolution. Defering disconnection until those finish.']]); + + Promise.all(setToArray(instance._runningCommands)).then(() => { // This one will go through success path + setImmediate(() => { + expect(loggerMock.debug.mock.calls).toEqual([['Pending commands finished successfully, disconnecting.']]); + expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously + }); }); - }); - }, 10); + }, 10); + }); }); - }); + }, 10); }, 10); - }, 10); - setTimeout(() => { - done(); - }, 400); + setTimeout(() => { + done(); + }, 400); + }); + }); diff --git a/src/utils/inputValidation/__tests__/apiKey.spec.ts b/src/utils/inputValidation/__tests__/apiKey.spec.ts index a5c3e908..23d75893 100644 --- a/src/utils/inputValidation/__tests__/apiKey.spec.ts +++ b/src/utils/inputValidation/__tests__/apiKey.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateApiKey, validateAndTrackApiKey, releaseApiKey } from '../apiKey'; @@ -25,13 +25,13 @@ const invalidKeys = [ describe('validateApiKey', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should return the passed api key if it is a valid string without logging any errors', () => { const validApiKey = 'qjok3snti4dgsticade5hfphmlucarsflv14'; expect(validateApiKey(loggerMock, validApiKey)).toBe(validApiKey); // It should return the passed string if it is valid. expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - - mockClear(); }); test('Should return false and log error if the api key is invalid', () => { @@ -44,13 +44,13 @@ describe('validateApiKey', () => { loggerMock.error.mockClear(); } - - mockClear(); }); }); describe('validateAndTrackApiKey', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should log a warning if we are instantiating more than one factory (different api keys)', () => { const validApiKey1 = 'qjok3snti4dgsticade5hfphmlucarsflv14'; const validApiKey2 = 'qjok3snti4dgsticade5hfphmlucars92uih'; @@ -70,13 +70,12 @@ describe('validateAndTrackApiKey', () => { releaseApiKey(validApiKey2); releaseApiKey(validApiKey3); - mockClear(); + loggerMock.mockClear(); expect(validateAndTrackApiKey(loggerMock, validApiKey1)).toBe(validApiKey1); expect(loggerMock.warn.mock.calls.length).toBe(0); // If all the keys were released and we try again, there is no warning. releaseApiKey(validApiKey1); // clean up the cache of api keys for next test - mockClear(); }); test('Should log a warning if we are instantiating more than one factory (same api key)', () => { @@ -104,7 +103,7 @@ describe('validateAndTrackApiKey', () => { releaseApiKey(validApiKey); releaseApiKey(validApiKey); - mockClear(); + loggerMock.mockClear(); // So we get the warning again. expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); @@ -114,12 +113,11 @@ describe('validateAndTrackApiKey', () => { releaseApiKey(validApiKey); releaseApiKey(validApiKey); - mockClear(); + loggerMock.mockClear(); expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); expect(loggerMock.warn.mock.calls.length).toBe(0); // s users, there is no warning when we use it again. releaseApiKey(validApiKey); // clean up the cache just in case a new test is added - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/attributes.spec.ts b/src/utils/inputValidation/__tests__/attributes.spec.ts index 17356188..c91310b4 100644 --- a/src/utils/inputValidation/__tests__/attributes.spec.ts +++ b/src/utils/inputValidation/__tests__/attributes.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateAttributes } from '../attributes'; @@ -18,14 +18,14 @@ const invalidAttributes = [ describe('INPUT VALIDATION for Attributes', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should return the passed object if it is a valid attributes map without logging any errors', () => { const validAttributes = { amIvalid: 'yes', 'are_you_sure': true, howMuch: 10 }; expect(validateAttributes(loggerMock, validAttributes, 'some_method_attrs')).toEqual(validAttributes); // It should return the passed map if it is valid. expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear; }); test('Should return the passed value if it is null or undefined (since attributes are optional) without logging any errors', () => { @@ -33,8 +33,6 @@ describe('INPUT VALIDATION for Attributes', () => { expect(validateAttributes(loggerMock, undefined, 'some_method_attrs')).toBe(undefined); // It should return the passed undefined. expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('Should return false and log error if attributes map is invalid', () => { @@ -48,7 +46,5 @@ describe('INPUT VALIDATION for Attributes', () => { } expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/event.spec.ts b/src/utils/inputValidation/__tests__/event.spec.ts index 4c6c9b57..9abfdff1 100644 --- a/src/utils/inputValidation/__tests__/event.spec.ts +++ b/src/utils/inputValidation/__tests__/event.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateEvent } from '../event'; @@ -33,6 +33,8 @@ const invalidEvents = [ describe('INPUT VALIDATION for Event types', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should return the provided event type if it is a valid string without logging any errors', () => { expect(validateEvent(loggerMock, 'valid:Too', 'some_method_eventType')).toBe('valid:Too'); // It should return the provided string if it is valid. @@ -43,8 +45,6 @@ describe('INPUT VALIDATION for Event types', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('Should return false and log error if event type is not a valid string', () => { @@ -59,7 +59,5 @@ describe('INPUT VALIDATION for Event types', () => { } expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/eventProperties.spec.ts b/src/utils/inputValidation/__tests__/eventProperties.spec.ts index 08dd5d51..3f2caa9b 100644 --- a/src/utils/inputValidation/__tests__/eventProperties.spec.ts +++ b/src/utils/inputValidation/__tests__/eventProperties.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateEventProperties } from '../eventProperties'; @@ -34,6 +34,8 @@ const invalidValues = [ describe('INPUT VALIDATION for Event Properties', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Not setting the properties object is acceptable', () => { expect(validateEventProperties(loggerMock, undefined, 'some_method_eventProps')).toEqual({ properties: null, @@ -48,8 +50,6 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('When setting a value for properties, only objects are acceptable', () => { @@ -65,8 +65,6 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('It should return the properties object when valid and also the correct event size', () => { @@ -91,8 +89,6 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('It should return the properties object when valid and also the correct event size, nulling any invalid prop', () => { @@ -127,8 +123,6 @@ describe('INPUT VALIDATION for Event Properties', () => { ['willBeNulled1', 'willBeNulled2', 'willBeNulled3', 'willBeNulled4'].forEach((key, index) => { expect(loggerMock.warn.mock.calls[index][0]).toBe(`some_method_eventProps: Property ${key} is of invalid type. Setting value to null.`); }); - - mockClear(); }); test('It should log a warning if the object has more than the max amount of allowed keys, logging a warning and returning the event (if other validations pass)', () => { @@ -160,8 +154,6 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls).toEqual([['some_method_eventProps: Event has more than 300 properties. Some of them will be trimmed when processed.']]); // It should have logged a warning. - - mockClear(); }); const fiveHundredChars = 'JKHSAKFJASHFJKASHSFKHAKJSGJKASGH1234567890JASHGJHASGJKAHSJKGHAJKSHGJKAHGJKASHajksghkjahsgjkhsakjghjkashgjkhagjkhajksghjkahsgjksahgjkahsgjkhasgjkhsagjkabsgjhaenjkrnjkwnqrkjnqwekjrnkjweqntkjnjkenasdjkngjksdajkghkjdasgkjnadsjgn asdkjgnkjsadngkjnasdjkngjknasdkjgnasdlgnsdakgnlkasndugbuoewqoitnwlkgadsgjdnsagubadisugboisdngklasdgndsgbjasdbgjkasbdgubuiqwetoiqhweiojtioweqhtiohqweiohtiowqehtoihewqiobtgoiqwengiowqnegionwqeogiqwneoignqiowegnioqewgnwqoiegnoiqwengiowqnegoinqwgionqwegionwqeoignqwegoinoiadnfaosignoiansgk'; @@ -198,9 +190,5 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. expect(loggerMock.error.mock.calls).toEqual([['some_method_eventProps: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.']]); // Should log an error. - - loggerMock.error.mockClear(); - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/eventValue.spec.ts b/src/utils/inputValidation/__tests__/eventValue.spec.ts index 900d9eae..b98ca3c0 100644 --- a/src/utils/inputValidation/__tests__/eventValue.spec.ts +++ b/src/utils/inputValidation/__tests__/eventValue.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateEventValue } from '../eventValue'; @@ -19,6 +19,8 @@ const invalidValues = [ describe('INPUT VALIDATION for Event Values', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should return the passed value if it is a valid finite number without logging any errors', () => { expect(validateEventValue(loggerMock, 50, 'some_method_eventValue')).toBe(50); // It should return the passed number if it is valid. expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. @@ -26,8 +28,6 @@ describe('INPUT VALIDATION for Event Values', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('Should return the passed value if it is a null or undefined (since it is optional) without logging any errors', () => { @@ -37,8 +37,6 @@ describe('INPUT VALIDATION for Event Values', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('Should return false and log error if event value is not a valid finite number', () => { @@ -52,7 +50,5 @@ describe('INPUT VALIDATION for Event Values', () => { } expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/isOperational.spec.ts b/src/utils/inputValidation/__tests__/isOperational.spec.ts index 5bdcb3b9..e5ab45b8 100644 --- a/src/utils/inputValidation/__tests__/isOperational.spec.ts +++ b/src/utils/inputValidation/__tests__/isOperational.spec.ts @@ -1,9 +1,11 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateIfNotDestroyed, validateIfOperational } from '../isOperational'; describe('validateIfNotDestroyed', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should return true if the client/factory evaluates as operational (not destroyed).', () => { const readinessManagerMock = { isDestroyed: jest.fn(() => false) }; @@ -12,8 +14,6 @@ describe('validateIfNotDestroyed', () => { expect(readinessManagerMock.isDestroyed.mock.calls.length).toBe(1); // It checks for destroyed status using the context. expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. - - mockClear(); }); test('Should return false and log error if attributes map is invalid', () => { @@ -24,8 +24,6 @@ describe('validateIfNotDestroyed', () => { expect(readinessManagerMock.isDestroyed.mock.calls.length).toBe(1); // It checks for destroyed status using the context. expect(loggerMock.error.mock.calls).toEqual([['Client has already been destroyed - no calls possible.']]); // Should log an error. expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. - - mockClear(); }); }); @@ -39,8 +37,6 @@ describe('validateIfOperational', () => { expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for readiness status using the context. expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. - - mockClear(); }); test('Should return true and log nothing if the SDK was ready from cache.', () => { @@ -52,8 +48,6 @@ describe('validateIfOperational', () => { expect(readinessManagerMock.isReadyFromCache.mock.calls.length).toBe(1); // It checks for SDK_READY_FROM_CACHE status. expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. - - mockClear(); }); test('Should return false and log a warning if the SDK was not ready.', () => { @@ -65,7 +59,5 @@ describe('validateIfOperational', () => { expect(readinessManagerMock.isReadyFromCache.mock.calls.length).toBe(1); // It checks for SDK_READY_FROM_CACHE status. expect(loggerMock.warn.mock.calls).toEqual([['test_method: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.']]); // It should log the expected warning. expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/key.spec.ts b/src/utils/inputValidation/__tests__/key.spec.ts index 703242b5..62600870 100644 --- a/src/utils/inputValidation/__tests__/key.spec.ts +++ b/src/utils/inputValidation/__tests__/key.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateKey } from '../key'; @@ -42,6 +42,8 @@ const invalidKeyObjects = [ describe('INPUT VALIDATION for Key', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('String and Object keys / Should return the key with no errors logged if the key is correct', () => { const validKey = 'validKey'; const validObjKey = { @@ -55,8 +57,6 @@ describe('INPUT VALIDATION for Key', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // No errors should be logged. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('String key / Should return false and log error if key is invalid', () => { @@ -71,8 +71,6 @@ describe('INPUT VALIDATION for Key', () => { } expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('String key / Should return stringified version of the key if it is convertible to one and log a warning.', () => { @@ -87,8 +85,6 @@ describe('INPUT VALIDATION for Key', () => { } expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. - - mockClear(); }); test('Object key / Should return false and log error if a part of the key is invalid', () => { @@ -102,7 +98,7 @@ describe('INPUT VALIDATION for Key', () => { expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - mockClear(); + loggerMock.mockClear(); // Test invalid matchingKey for (let i = 0; i < invalidKeys.length; i++) { const invalidKey = { @@ -119,7 +115,7 @@ describe('INPUT VALIDATION for Key', () => { expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - mockClear(); + loggerMock.mockClear(); // Test invalid bucketingKey for (let i = 0; i < invalidKeys.length; i++) { @@ -137,7 +133,7 @@ describe('INPUT VALIDATION for Key', () => { expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - mockClear(); + loggerMock.mockClear(); // Just one test that if both are invalid we get the log for both. let invalidKey = { @@ -152,8 +148,6 @@ describe('INPUT VALIDATION for Key', () => { expect(loggerMock.error.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The error should be logged for the invalid key property. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('Object key / Should return stringified version of the key props if those are convertible and log the corresponding warnings', () => { @@ -173,7 +167,5 @@ describe('INPUT VALIDATION for Key', () => { expect(loggerMock.warn.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The warning should be logged for the stringified prop if warnings are enabled. expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/split.spec.ts b/src/utils/inputValidation/__tests__/split.spec.ts index b3afbfe5..1a6417b9 100644 --- a/src/utils/inputValidation/__tests__/split.spec.ts +++ b/src/utils/inputValidation/__tests__/split.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateSplit } from '../split'; @@ -35,6 +35,8 @@ const trimmableSplits = [ describe('INPUT VALIDATION for Split name', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should return the provided split name if it is a valid string without logging any errors', () => { expect(validateSplit(loggerMock, 'splitName', 'some_method_splitName')).toBe('splitName'); // It should return the provided string if it is valid. expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. @@ -44,8 +46,6 @@ describe('INPUT VALIDATION for Split name', () => { expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('Should trim split name if it is a valid string with trimmable spaces and log a warning (if those are enabled)', () => { @@ -58,8 +58,6 @@ describe('INPUT VALIDATION for Split name', () => { } expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. - - mockClear(); }); test('Should return false and log error if split name is not a valid string', () => { @@ -75,7 +73,5 @@ describe('INPUT VALIDATION for Split name', () => { } expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/splitExistance.spec.ts b/src/utils/inputValidation/__tests__/splitExistance.spec.ts index c1f25d2c..ae1cfd5f 100644 --- a/src/utils/inputValidation/__tests__/splitExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/splitExistance.spec.ts @@ -1,7 +1,7 @@ import * as LabelConstants from '../../labels'; -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateSplitExistance } from '../splitExistance'; import { IReadinessManager } from '../../../readiness/types'; @@ -12,6 +12,8 @@ const errorMsgs = { describe('Split existance (special case)', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should return a boolean indicating if the SDK was ready and there was no Split object or "definition not found" label', () => { // @ts-expect-error let readinessManagerMock = { @@ -44,7 +46,5 @@ describe('Split existance (special case)', () => { loggerMock.warn.mock.calls.forEach(call => expect(call[0]).toBe(`other_method: ${errorMsgs.NOT_EXISTENT_SPLIT('other_split')}`)); // Warning logs should have the correct message. expect(loggerMock.error.mock.calls.length).toBe(0); // We log warnings, not errors. - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/splits.spec.ts b/src/utils/inputValidation/__tests__/splits.spec.ts index eba948d3..1bbe14d0 100644 --- a/src/utils/inputValidation/__tests__/splits.spec.ts +++ b/src/utils/inputValidation/__tests__/splits.spec.ts @@ -2,7 +2,7 @@ import uniq from 'lodash/uniq'; import startsWith from 'lodash/startsWith'; // mocks sdkLogger -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; // mocks validateSplit jest.mock('../split'); @@ -34,7 +34,7 @@ const invalidSplits = [ describe('INPUT VALIDATION for Split names', () => { afterEach(() => { - mockClear(); + loggerMock.mockClear(); validateSplitMock.mockClear(); }); diff --git a/src/utils/inputValidation/__tests__/trafficType.spec.ts b/src/utils/inputValidation/__tests__/trafficType.spec.ts index 9e18d271..2b5af848 100644 --- a/src/utils/inputValidation/__tests__/trafficType.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficType.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateTrafficType } from '../trafficType'; @@ -35,6 +35,8 @@ const convertibleTrafficTypes = [ describe('INPUT VALIDATION for Traffic Types', () => { + afterEach(() => { loggerMock.mockClear(); }); + test('Should return the provided traffic type if it is a valid string without logging any errors', () => { expect(validateTrafficType(loggerMock, 'traffictype', 'some_method_trafficType')).toBe('traffictype'); // It should return the provided string if it is valid. expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. @@ -44,8 +46,6 @@ describe('INPUT VALIDATION for Traffic Types', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); test('Should lowercase the whole traffic type if it is a valid string with uppercases and log a warning (if those are enabled)', () => { @@ -57,8 +57,6 @@ describe('INPUT VALIDATION for Traffic Types', () => { } expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. - - mockClear(); }); test('Should return false and log error if traffic type is not a valid string', () => { @@ -71,7 +69,5 @@ describe('INPUT VALIDATION for Traffic Types', () => { } expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. - - mockClear(); }); }); diff --git a/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts b/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts index 131c9b84..f8e30bd7 100644 --- a/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts @@ -4,7 +4,7 @@ import { LOCALHOST_MODE, STANDALONE_MODE } from '../../constants'; import thenable from '../../promise/thenable'; /** Mocks */ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; const TEST_EXISTENT_TT = 'test_existent_tt'; const TEST_NOT_EXISTENT_TT = 'test_not_existent_tt'; @@ -35,6 +35,11 @@ const errorMsgs = { describe('validateTrafficTypeExistance', () => { + afterEach(() => { + loggerMock.mockClear(); + splitsCacheMock.trafficTypeExists.mockClear(); + }); + test('Should return true without going to the storage and log nothing if the SDK is not ready or in localhost mode', () => { // Not ready and not localstorage expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is not ready yet, it will return true. @@ -48,8 +53,6 @@ describe('validateTrafficTypeExistance', () => { expect(splitsCacheMock.trafficTypeExists.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it does not try to go to the storage. expect(loggerMock.warn.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any warnings. expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any errors. - - mockClear(); }); test('Should return true and log nothing if SDK Ready, not localhost mode and the traffic type exists in the storage', () => { @@ -60,9 +63,6 @@ describe('validateTrafficTypeExistance', () => { expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_EXISTENT_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the storage. expect(loggerMock.warn.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any warnings. expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any errors. - - mockClear(); - splitsCacheMock.trafficTypeExists.mockClear(); }); test('Should return false and log warning if SDK Ready, not localhost mode and the traffic type does NOT exist in the storage', () => { @@ -71,9 +71,6 @@ describe('validateTrafficTypeExistance', () => { expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_NOT_EXISTENT_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the storage. expect(loggerMock.warn.mock.calls).toEqual([[`test_method_y: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. expect(loggerMock.error.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. - - mockClear(); - splitsCacheMock.trafficTypeExists.mockClear(); }); test('validateTrafficTypeExistance w/async storage - If the storage is async but the SDK is in condition to validate, it will validate that the TT exists on the storage', async () => { @@ -104,8 +101,5 @@ describe('validateTrafficTypeExistance', () => { expect(isValid2).toBe(false); // As the split is not on the storage, it will resolve to false, failing the validation.. expect(loggerMock.warn.mock.calls).toEqual([[`test_method_z: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_ASYNC_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. expect(loggerMock.error.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. - - mockClear(); - splitsCacheMock.trafficTypeExists.mockClear(); }); }); diff --git a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts index 2acacfa0..d46117e5 100644 --- a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts +++ b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts @@ -1,4 +1,4 @@ -import { loggerMock, mockClear } from '../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { STANDALONE_MODE, CONSUMER_MODE } from '../../constants'; @@ -16,6 +16,8 @@ describe('validateSplitFilters', () => { groupedFilters: { byName: [], byPrefix: [] } }; + afterEach(() => { loggerMock.mockClear(); }); + test('Returns default output with empty values if `splitFilters` is an invalid object or `mode` is not \'standalone\'', () => { expect(validateSplitFilters(loggerMock, undefined, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array @@ -39,8 +41,6 @@ describe('validateSplitFilters', () => { expect(loggerMock.debug.mock.calls.length === 0).toBe(true); expect(loggerMock.error.mock.calls.length === 0).toBe(true); - - mockClear(); }); test('Returns object with null queryString, if `splitFilters` contains invalid filters or contains filters with no values or invalid values', () => { @@ -76,8 +76,6 @@ describe('validateSplitFilters', () => { ['Factory instantiation: you passed an invalid byName filter value, byName filter value must be a non-empty string.'], ['Factory instantiation: byName filter must be a non-empty array.'] ]); - - mockClear(); }); test('Returns object with a queryString, if `splitFilters` contains at least a valid `byName` or `byPrefix` filter with at least a valid value', () => { @@ -97,8 +95,6 @@ describe('validateSplitFilters', () => { expect(() => validateSplitFilters(loggerMock, splitFilters[i], STANDALONE_MODE)).toThrow(queryStrings[i]); } } - - mockClear(); }); }); From 40ad2e0e9df3082f4cc9ac971a19d086dd097bf1 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 11 Mar 2021 17:31:32 -0300 Subject: [PATCH 29/58] polishing --- src/logger/__tests__/index.spec.ts | 5 +---- src/logger/__tests__/sdkLogger.spec.ts | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index cfb95331..b56491d2 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -33,10 +33,7 @@ test('SPLIT LOGGER / Logger class shape', () => { expect(typeof logger.info).toBe('function'); // instance.info should be a method. expect(typeof logger.warn).toBe('function'); // instance.warn should be a method. expect(typeof logger.error).toBe('function'); // instance.error should be a method. - expect(typeof logger.setLogLevel).toBe('function'); // @ts-ignore // instance.setLogLevel should be a method. - expect(typeof logger.options.logLevel).toBe('string'); // @ts-ignore // instance.options.logLevel should be a string. - expect(typeof logger.options.showLevel).toBe('boolean'); // instance.options.showLevel should be a boolean. - + expect(typeof logger.setLogLevel).toBe('function'); // instance.setLogLevel should be a method. }); const LOG_LEVELS_IN_ORDER = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE']; diff --git a/src/logger/__tests__/sdkLogger.spec.ts b/src/logger/__tests__/sdkLogger.spec.ts index 230861a1..2d8743d8 100644 --- a/src/logger/__tests__/sdkLogger.spec.ts +++ b/src/logger/__tests__/sdkLogger.spec.ts @@ -6,25 +6,25 @@ test('createLoggerAPI / methods and props', () => { expect(typeof createLoggerAPI).toBe('function'); // Importing the module should return a function. - const loggerAPI = createLoggerAPI(logger); + const API = createLoggerAPI(logger); - expect(typeof loggerAPI).toBe('object'); // Our logger should expose an API object. + expect(typeof API).toBe('object'); // Our logger should expose an API object. - expect(typeof loggerAPI.setLogLevel).toBe('function'); // API object should have setLogLevel method. - loggerAPI.setLogLevel('INFO'); // @ts-ignore + expect(typeof API.setLogLevel).toBe('function'); // API object should have setLogLevel method. + API.setLogLevel('INFO'); // @ts-ignore expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel should update the log level. // @ts-ignore - loggerAPI.setLogLevel('warn'); // @ts-ignore + API.setLogLevel('warn'); // @ts-ignore expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel with an invalid value should not update the log level. - expect(typeof loggerAPI.enable).toBe('function'); // API object should have enable method. - loggerAPI.enable(); // @ts-ignore + expect(typeof API.enable).toBe('function'); // API object should have enable method. + API.enable(); // @ts-ignore expect(logger.options.logLevel).toBe('DEBUG'); // calling enable should update logger log level to DEBUG. - expect(typeof loggerAPI.disable).toBe('function'); // API object should have disable method. - loggerAPI.disable(); // @ts-ignore + expect(typeof API.disable).toBe('function'); // API object should have disable method. + API.disable(); // @ts-ignore expect(logger.options.logLevel).toBe('NONE'); // calling disable should update logger log level to NONE. - expect(loggerAPI.LogLevel).toEqual(LogLevels); // API object should have LogLevel prop including all available levels. + expect(API.LogLevel).toEqual(LogLevels); // API object should have LogLevel prop including all available levels. }); From 38ced46bb9d7d30408d2761b8227f8e5bc836f8a Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 11 Mar 2021 17:38:56 -0300 Subject: [PATCH 30/58] more polishing --- src/logger/__tests__/sdkLogger.spec.ts | 18 ++++++++---------- .../logger/pluggableLogger.ts | 3 +-- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/logger/__tests__/sdkLogger.spec.ts b/src/logger/__tests__/sdkLogger.spec.ts index 2d8743d8..6776e679 100644 --- a/src/logger/__tests__/sdkLogger.spec.ts +++ b/src/logger/__tests__/sdkLogger.spec.ts @@ -1,28 +1,26 @@ import { createLoggerAPI } from '../sdkLogger'; import { Logger, LogLevels } from '../index'; -test('createLoggerAPI / methods and props', () => { - const logger = new Logger('category', {}); - - expect(typeof createLoggerAPI).toBe('function'); // Importing the module should return a function. - +test('LoggerAPI / methods and props', () => { + // creates a LoggerAPI instance + const logger = new Logger('category'); const API = createLoggerAPI(logger); expect(typeof API).toBe('object'); // Our logger should expose an API object. expect(typeof API.setLogLevel).toBe('function'); // API object should have setLogLevel method. - API.setLogLevel('INFO'); // @ts-ignore + API.setLogLevel('INFO'); // @ts-ignore, accessing private prop expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel should update the log level. - // @ts-ignore - API.setLogLevel('warn'); // @ts-ignore + // @ts-ignore, passing wrong type + API.setLogLevel('warn'); // @ts-ignore, accessing private prop expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel with an invalid value should not update the log level. expect(typeof API.enable).toBe('function'); // API object should have enable method. - API.enable(); // @ts-ignore + API.enable(); // @ts-ignore, accessing private prop expect(logger.options.logLevel).toBe('DEBUG'); // calling enable should update logger log level to DEBUG. expect(typeof API.disable).toBe('function'); // API object should have disable method. - API.disable(); // @ts-ignore + API.disable(); // @ts-ignore, accessing private prop expect(logger.options.logLevel).toBe('NONE'); // calling disable should update logger log level to NONE. expect(API.LogLevel).toEqual(LogLevels); // API object should have LogLevel prop including all available levels. diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index 4ae66f49..917c528a 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -8,8 +8,7 @@ const noopLogger: ILogger = { error() { } }; -function isLogger(log: unknown): log is ILogger { - // @ts-ignore +function isLogger(log: any): log is ILogger { return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function' && typeof log.setLogLevel === 'function'; } From d6b71d35adb8bc9962d3f75341256efb04722dd4 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 11 Mar 2021 18:22:04 -0300 Subject: [PATCH 31/58] polishing --- .eslintrc | 3 ++- src/integrations/ga/SplitToGa.ts | 5 +++-- src/sdkClient/sdkClientMethodCS.ts | 6 ++++-- src/sdkClient/sdkClientMethodCSWithTT.ts | 10 ++++++---- src/services/splitHttpClient.ts | 2 +- src/sync/offline/splitsParser/splitsParserFromFile.ts | 4 ++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4f5939ef..a44d175d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -67,7 +67,8 @@ ], "rules": { "no-restricted-syntax": ["error", "ForOfStatement", "ForInStatement", "ArrayPattern"], - "compat/compat": ["error", "defaults, not ie < 10, not node < 6"] + "compat/compat": ["error", "defaults, not ie < 10, not node < 6"], + "no-throw-literal": "error" }, "parserOptions": { "ecmaVersion": 2015, diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index 92e93365..0ac29ceb 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -9,6 +9,7 @@ import { ILogger } from '../../logger/types'; // const log = logFactory('splitio-split-to-ga'); const noGaWarning = '`ga` command queue not found.'; +const noHit = 'No hit was sent.'; export default class SplitToGa implements IIntegration { @@ -115,7 +116,7 @@ export default class SplitToGa implements IIntegration { if (!fieldsObject || !SplitToGa.validateFieldsObject(this.log, fieldsObject)) return; } } catch (err) { - this.log.warn(`SplitToGa queue method threw: ${err}. No hit was sent.`); + this.log.warn(`SplitToGa queue method threw: ${err}. ${noHit}`); return; } @@ -128,7 +129,7 @@ export default class SplitToGa implements IIntegration { ga(sendCommand, fieldsObject); }); } else { - this.log.warn(`${noGaWarning} No hit was sent.`); + this.log.warn(`${noGaWarning} ${noHit}`); } } diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index 9cbaea51..fc8a9da5 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -16,6 +16,8 @@ function buildInstanceId(key: SplitIO.SplitKey) { return `${key.matchingKey ? key.matchingKey : key}-${key.bucketingKey ? key.bucketingKey : key}-`; } +const method = 'Client instantiation'; + /** * Factory of client method for the client-side API variant where TT is ignored and thus * clients don't have a binded TT for the track method. @@ -26,7 +28,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? // Keeping similar behaviour as in the isomorphic JS SDK: if settings key is invalid, // `false` value is used as binded key of the default client, but trafficType is ignored // @TODO handle as a non-recoverable error - const validKey = validateKey(log, key, 'Client instantiation'); + const validKey = validateKey(log, key, method); const mainClientInstance = clientCSDecorator( sdkClientFactory(params) as SplitIO.IClient, // @ts-ignore @@ -47,7 +49,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? } // Validate the key value. The trafficType (2nd argument) is ignored - const validKey = validateKey(log, key, 'Shared Client instantiation'); + const validKey = validateKey(log, key, `Shared ${method}`); if (validKey === false) { throw new Error('Shared Client needs a valid key.'); } diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index 94c1b638..9145ec0e 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -17,6 +17,8 @@ function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string) { return `${key.matchingKey ? key.matchingKey : key}-${key.bucketingKey ? key.bucketingKey : key}-${trafficType !== undefined ? trafficType : ''}`; } +const method = 'Client instantiation'; + /** * Factory of client method for the client-side (browser) variant of the Isomorphic JS SDK, * where clients can have a binded TT for the track method, which is provided via the settings @@ -28,10 +30,10 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? // Keeping the behaviour as in the isomorphic JS SDK: if settings key or TT are invalid, // `false` value is used as binded key/TT of the default client, which leads to several issues. // @TODO update when supporting non-recoverable errors - const validKey = validateKey(log, key, 'Client instantiation'); + const validKey = validateKey(log, key, method); let validTrafficType; if (trafficType !== undefined) { - validTrafficType = validateTrafficType(log, trafficType, 'Client instantiation'); + validTrafficType = validateTrafficType(log, trafficType, method); } const mainClientInstance = clientCSDecorator( @@ -54,14 +56,14 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? } // Validate the key value - const validKey = validateKey(log, key, 'Shared Client instantiation'); + const validKey = validateKey(log, key, `Shared ${method}`); if (validKey === false) { throw new Error('Shared Client needs a valid key.'); } let validTrafficType; if (trafficType !== undefined) { - validTrafficType = validateTrafficType(log, trafficType, 'Shared Client instantiation'); + validTrafficType = validateTrafficType(log, trafficType, `Shared ${method}`); if (validTrafficType === false) { throw new Error('Shared Client needs a valid traffic type or no traffic type at all.'); } diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index 3386aebb..5edecb41 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -47,7 +47,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I return fetch ? fetch(url, request) // https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful .then(response => { - if (!response.ok) { + if (!response.ok) { // eslint-disable-next-line no-throw-literal throw { response }; } return response; diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index 7161c44a..f9cce80f 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -32,10 +32,10 @@ function configFilesPath(configFilePath?: SplitIO.MockedFeaturesFilePath): Split // Validate the extensions if (!(endsWith(configFilePath, '.yaml', true) || endsWith(configFilePath, '.yml', true) || endsWith(configFilePath, '.split', true))) - throw `Invalid extension specified for Splits mock file. Accepted extensions are ".yml" and ".yaml". Your specified file is ${configFilePath}`; + throw new Error(`Invalid extension specified for Splits mock file. Accepted extensions are ".yml" and ".yaml". Your specified file is ${configFilePath}`); if (!fs.existsSync(configFilePath as SplitIO.MockedFeaturesFilePath)) - throw `Split configuration not found in ${configFilePath} - Please review your Split file location.`; + throw new Error(`Split configuration not found in ${configFilePath} - Please review your Split file location.`); return configFilePath as SplitIO.MockedFeaturesFilePath; } From 8fa1e2295d074c1b76da6d3487e01038775bd454 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 11 Mar 2021 19:11:44 -0300 Subject: [PATCH 32/58] eslint rule for throwing error objects --- .eslintrc | 3 ++- src/services/splitHttpClient.ts | 2 +- src/sync/offline/splitsParser/splitsParserFromFile.ts | 4 ++-- src/utils/settingsValidation/logger/pluggableLogger.ts | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4f5939ef..a44d175d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -67,7 +67,8 @@ ], "rules": { "no-restricted-syntax": ["error", "ForOfStatement", "ForInStatement", "ArrayPattern"], - "compat/compat": ["error", "defaults, not ie < 10, not node < 6"] + "compat/compat": ["error", "defaults, not ie < 10, not node < 6"], + "no-throw-literal": "error" }, "parserOptions": { "ecmaVersion": 2015, diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index 4ced607f..e608fb87 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -46,7 +46,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I return fetch ? fetch(url, request) // https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful .then(response => { - if (!response.ok) { + if (!response.ok) { // eslint-disable-next-line no-throw-literal throw { response }; } return response; diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index a94eb997..6c315b97 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -31,10 +31,10 @@ function configFilesPath(configFilePath?: SplitIO.MockedFeaturesFilePath): Split // Validate the extensions if (!(endsWith(configFilePath, '.yaml', true) || endsWith(configFilePath, '.yml', true) || endsWith(configFilePath, '.split', true))) - throw `Invalid extension specified for Splits mock file. Accepted extensions are ".yml" and ".yaml". Your specified file is ${configFilePath}`; + throw new Error(`Invalid extension specified for Splits mock file. Accepted extensions are ".yml" and ".yaml". Your specified file is ${configFilePath}`); if (!fs.existsSync(configFilePath as SplitIO.MockedFeaturesFilePath)) - throw `Split configuration not found in ${configFilePath} - Please review your Split file location.`; + throw new Error(`Split configuration not found in ${configFilePath} - Please review your Split file location.`); return configFilePath as SplitIO.MockedFeaturesFilePath; } diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index 917c528a..8e01d90c 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -26,5 +26,6 @@ export function validateLogger(settings: { debug: unknown }): ILogger { if (isLogger(debug)) return debug; + // @TODO log error instead of throwing one throw new Error('The provided `debug` value at config is not valid'); } From 5c562dc03454a43c69b616b26bb22ae08be8ee2c Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 16 Mar 2021 17:04:08 -0300 Subject: [PATCH 33/58] pluggable loggers --- src/logger/browser/debugLogger.ts | 9 + src/logger/browser/errorLogger.ts | 5 + src/logger/browser/infoLogger.ts | 7 + src/logger/browser/warnLogger.ts | 6 + src/logger/constants.ts | 272 +++++++++--------- src/logger/index.ts | 23 +- src/logger/messages/debug.ts | 44 +++ src/logger/messages/debugBrowser.ts | 6 + src/logger/messages/debugNode.ts | 14 + src/logger/messages/error.ts | 37 +++ src/logger/messages/errorNode.ts | 7 + src/logger/messages/info.ts | 26 ++ src/logger/messages/warn.ts | 29 ++ src/logger/messages/warnNode.ts | 5 + src/logger/types.ts | 8 +- .../__tests__/attributes.spec.ts | 3 +- .../logger/builtinLogger.ts | 29 +- .../logger/pluggableLogger.ts | 24 +- 18 files changed, 379 insertions(+), 175 deletions(-) create mode 100644 src/logger/browser/debugLogger.ts create mode 100644 src/logger/browser/errorLogger.ts create mode 100644 src/logger/browser/infoLogger.ts create mode 100644 src/logger/browser/warnLogger.ts create mode 100644 src/logger/messages/debug.ts create mode 100644 src/logger/messages/debugBrowser.ts create mode 100644 src/logger/messages/debugNode.ts create mode 100644 src/logger/messages/error.ts create mode 100644 src/logger/messages/errorNode.ts create mode 100644 src/logger/messages/info.ts create mode 100644 src/logger/messages/warn.ts create mode 100644 src/logger/messages/warnNode.ts diff --git a/src/logger/browser/debugLogger.ts b/src/logger/browser/debugLogger.ts new file mode 100644 index 00000000..84962c0d --- /dev/null +++ b/src/logger/browser/debugLogger.ts @@ -0,0 +1,9 @@ +import { Logger } from '../index'; +import { codesError } from '../messages/error'; +import { codesWarn } from '../messages/warn'; +import { codesInfo } from '../messages/info'; +import { codesDebug } from '../messages/debug'; +import { codesDebugBrowser } from '../messages/debugBrowser'; +import { _Map } from '../../utils/lang/maps'; + +export const debugLogger = new Logger('splitio', { logLevel: 'DEBUG' }, new _Map(codesError.concat(codesWarn).concat(codesInfo).concat(codesDebug).concat(codesDebugBrowser))); diff --git a/src/logger/browser/errorLogger.ts b/src/logger/browser/errorLogger.ts new file mode 100644 index 00000000..e9f84c2e --- /dev/null +++ b/src/logger/browser/errorLogger.ts @@ -0,0 +1,5 @@ +import { Logger } from '../index'; +import { codesError } from '../messages/error'; +import { _Map } from '../../utils/lang/maps'; + +export const errorLogger = new Logger('splitio', { logLevel: 'ERROR' }, new _Map(codesError)); diff --git a/src/logger/browser/infoLogger.ts b/src/logger/browser/infoLogger.ts new file mode 100644 index 00000000..196d2874 --- /dev/null +++ b/src/logger/browser/infoLogger.ts @@ -0,0 +1,7 @@ +import { Logger } from '../index'; +import { codesError } from '../messages/error'; +import { codesWarn } from '../messages/warn'; +import { codesInfo } from '../messages/info'; +import { _Map } from '../../utils/lang/maps'; + +export const infoLogger = new Logger('splitio', { logLevel: 'INFO' }, new _Map(codesError.concat(codesWarn).concat(codesInfo))); diff --git a/src/logger/browser/warnLogger.ts b/src/logger/browser/warnLogger.ts new file mode 100644 index 00000000..21fce48d --- /dev/null +++ b/src/logger/browser/warnLogger.ts @@ -0,0 +1,6 @@ +import { Logger } from '../index'; +import { codesError } from '../messages/error'; +import { codesWarn } from '../messages/warn'; +import { _Map } from '../../utils/lang/maps'; + +export const warnLogger = new Logger('splitio', { logLevel: 'WARN' }, new _Map(codesError.concat(codesWarn))); diff --git a/src/logger/constants.ts b/src/logger/constants.ts index eecf9f1c..77ef7339 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -1,151 +1,151 @@ // commons -export const DEBUG_0 = 'splitio-engine:combiner => [andCombiner] evaluates to %s'; -export const DEBUG_1 = 'splitio-engine:combiner => Treatment found: %s'; -export const DEBUG_2 = 'splitio-engine:combiner => All predicates evaluated, no treatment found.'; -export const DEBUG_3 = 'splitio-engine => [engine] using algo \'murmur\' bucket %s for key %s using seed %s - treatment %s'; -export const DEBUG_4 = 'splitio-engine:matcher => [allMatcher] is always true'; -export const DEBUG_5 = 'splitio-engine:matcher => [betweenMatcher] is %s between %s and %s? %s'; -export const DEBUG_6 = 'splitio-engine:matcher => [booleanMatcher] %s === %s'; -export const DEBUG_7 = 'splitio-engine:matcher => [containsAllMatcher] %s contains all elements of %s? %s'; -export const DEBUG_8 = 'splitio-engine:matcher => [containsAnyMatcher] %s contains at least an element of %s? %s'; -export const DEBUG_9 = 'splitio-engine:matcher => [containsStringMatcher] %s contains %s? %s'; -export const DEBUG_10 = 'splitio-engine:matcher => [dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'; -export const DEBUG_11 = 'splitio-engine:matcher => [dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'; -export const DEBUG_12 = 'splitio-engine:matcher => [equalToMatcher] is %s equal to %s? %s'; -export const DEBUG_13 = 'splitio-engine:matcher => [equalToSetMatcher] is %s equal to set %s? %s'; -export const DEBUG_14 = 'splitio-engine:matcher => [endsWithMatcher] %s ends with %s? %s'; -export const DEBUG_15 = 'splitio-engine:matcher => [greaterThanEqualMatcher] is %s greater than %s? %s'; -export const DEBUG_16 = 'splitio-engine:matcher => [lessThanEqualMatcher] is %s less than %s? %s'; -export const DEBUG_17 = 'splitio-engine:matcher => [partOfMatcher] %s is part of %s? %s'; -export const DEBUG_18 = 'splitio-engine:matcher => [asyncSegmentMatcher] evaluated %s / %s => %s'; -export const DEBUG_19 = 'splitio-engine:matcher => [segmentMatcher] evaluated %s / %s => %s'; -export const DEBUG_20 = 'splitio-engine:matcher => [stringMatcher] does %s matches with %s? %s'; -export const DEBUG_21 = 'splitio-engine:matcher => [stringMatcher] %s is an invalid regex'; -export const DEBUG_22 = 'splitio-engine:matcher => [startsWithMatcher] %s starts with %s? %s'; -export const DEBUG_23 = 'splitio-engine:matcher => [whitelistMatcher] evaluated %s in [%s] => %s'; -export const DEBUG_24 = 'splitio-engine:value => Extracted attribute [%s], [%s] will be used for matching.'; -export const DEBUG_25 = 'splitio-engine:sanitize => Attempted to sanitize [%s] which should be of type [%s]. \n Sanitized and processed value => [%s]'; -export const DEBUG_31 = 'splitio => Retrieving SDK client.'; -export const DEBUG_32 = 'splitio => Retrieving default SDK client.'; // @TODO remove and use 'splitio => Retrieving SDK client.' -export const DEBUG_33 = 'splitio => Retrieving existing SDK client.'; -export const DEBUG_36 = 'splitio-producer:offline => Splits data: '; -export const DEBUG_42 = 'splitio-sync:split-changes => Spin up split update using since = %s'; -export const DEBUG_43 = 'splitio-sync:split-changes => New splits %s'; -export const DEBUG_44 = 'splitio-sync:split-changes => Removed splits %s'; -export const DEBUG_45 = 'splitio-sync:split-changes => Segment names collected %s'; -export const DEBUG_46 = 'splitio-sync:sse-handler => New SSE message received, with data: %s.'; -export const DEBUG_47 = 'splitio-sync:task => Starting %s. Running each %s millis'; -export const DEBUG_48 = 'splitio-sync:task => Running %s'; -export const DEBUG_49 = 'splitio-sync:task => Stopping %s'; -export const DEBUG_50 = 'splitio-client:impressions-tracker => Successfully stored %s impression%s.'; -export const DEBUG_51 = 'Factory instantiation: splits filtering criteria is \'%s\'.'; +export const DEBUG_0 = 0; +export const DEBUG_1 = 1; +export const DEBUG_2 = 2; +export const DEBUG_3 = 3; +export const DEBUG_4 = 4; +export const DEBUG_5 = 5; +export const DEBUG_6 = 6; +export const DEBUG_7 = 7; +export const DEBUG_8 = 8; +export const DEBUG_9 = 9; +export const DEBUG_10 = 10; +export const DEBUG_11 = 11; +export const DEBUG_12 = 12; +export const DEBUG_13 = 13; +export const DEBUG_14 = 14; +export const DEBUG_15 = 15; +export const DEBUG_16 = 16; +export const DEBUG_17 = 17; +export const DEBUG_18 = 18; +export const DEBUG_19 = 19; +export const DEBUG_20 = 20; +export const DEBUG_21 = 21; +export const DEBUG_22 = 22; +export const DEBUG_23 = 23; +export const DEBUG_24 = 24; +export const DEBUG_25 = 25; +export const DEBUG_31 = 31; +export const DEBUG_32 = 32; // @TODO remove and use DEBUG_31 ('splitio => Retrieving SDK client.') +export const DEBUG_33 = 33; +export const DEBUG_36 = 36; +export const DEBUG_42 = 42; +export const DEBUG_43 = 43; +export const DEBUG_44 = 44; +export const DEBUG_45 = 45; +export const DEBUG_46 = 46; +export const DEBUG_47 = 47; +export const DEBUG_48 = 48; +export const DEBUG_49 = 49; +export const DEBUG_50 = 50; +export const DEBUG_51 = 51; // browser -export const DEBUG_26 = 'splitio-client:cleanup => Registering flush handler when unload page event is triggered.'; -export const DEBUG_27 = 'splitio-client:cleanup => Deregistering flush handler when unload page event is triggered.'; +export const DEBUG_26 = 26; +export const DEBUG_27 = 27; // node -export const DEBUG_28 = 'splitio-client:cleanup => Registering cleanup handlers.'; -export const DEBUG_29 = 'splitio-client:cleanup => Deregistering cleanup handlers.'; -export const DEBUG_30 = 'splitio-client:cleanup => Split SDK graceful shutdown after SIGTERM.'; -export const DEBUG_39 = 'splitio-sync:segment-changes => Processed %s with till = %s. Added: %s. Removed: %s'; -export const DEBUG_40 = 'splitio-sync:segment-changes => Processing segment %s'; -export const DEBUG_41 = 'splitio-sync:segment-changes => Started segments update'; -export const DEBUG_34 = 'splitio-offline:splits-fetcher => Ignoring empty line or comment at #%s'; -export const DEBUG_35 = 'splitio-offline:splits-fetcher => Ignoring line since it does not have exactly two columns #%s'; -export const DEBUG_37 = 'splitio-sync:polling-manager => Splits will be refreshed each %s millis'; // @TODO remove since we already log it in syncTask debug log? -export const DEBUG_38 = 'splitio-sync:polling-manager => Segments will be refreshed each %s millis'; // @TODO remove since we already log it in syncTask debug log? +export const DEBUG_28 = 28; +export const DEBUG_29 = 29; +export const DEBUG_30 = 30; +export const DEBUG_39 = 39; +export const DEBUG_40 = 40; +export const DEBUG_41 = 41; +export const DEBUG_34 = 34; +export const DEBUG_35 = 35; +export const DEBUG_37 = 37; // @TODO remove since we already log it in syncTask debug log? +export const DEBUG_38 = 38; // @TODO remove since we already log it in syncTask debug log? // commons -export const ERROR_0 = 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'; -export const ERROR_2 = 'splitio-utils:logger => Invalid Log Level - No changes to the logs will be applied.'; -export const ERROR_3 = 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'; -export const ERROR_4 = 'splitio => Manager instance is not available. Provide the manager module on settings.'; -export const ERROR_5 = 'splitio-services:service => %s The SDK will not get ready.'; -export const ERROR_7 = 'splitio-producer:offline => There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'; -export const ERROR_9 = 'splitio-sync:sse-handler => Fail to connect to streaming, with error message: %s'; -export const ERROR_10 = 'splitio-sync:push-manager => Failed to authenticate for streaming. Error: "%s".'; -export const ERROR_11 = 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'; -export const ERROR_12 = 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'; -export const ERROR_13 = '%s: attributes must be a plain object.'; -export const ERROR_14 = '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'; -export const ERROR_15 = '%s: you passed a null or undefined event_type, event_type must be a non-empty string.'; -export const ERROR_16 = '%s: you passed an invalid event_type, event_type must be a non-empty string.'; -export const ERROR_17 = '%s: you passed an empty event_type, event_type must be a non-empty string.'; -export const ERROR_18 = '%s: properties must be a plain object.'; -export const ERROR_19 = '%s: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'; -export const ERROR_20 = '%s: value must be a finite number.'; -export const ERROR_21 = 'Client has already been destroyed - no calls possible.'; -export const ERROR_22 = '%s: you passed a null or undefined %s, %s must be a non-empty string.'; -export const ERROR_23 = '%s: %s too long, %s must be 250 characters or less.'; -export const ERROR_24 = '%s: you passed an invalid %s type, %s must be a non-empty string.'; -export const ERROR_25 = '%s: you passed an empty string, %s must be a non-empty string.'; -export const ERROR_26 = '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'; -export const ERROR_32 = '%s: you passed an invalid %s, %s must be a non-empty string.'; -export const ERROR_33 = '%s: you passed an empty %s, %s must be a non-empty string.'; -export const ERROR_34 = '%s: %s must be a non-empty array.'; -export const ERROR_35 = '%s: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.'; -export const ERROR_36 = '%s: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.'; -export const ERROR_37 = '%s: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.'; -export const ERROR_38 = 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: \'%s\' or \'%s\'. Defaulting to \'%s\' mode.'; -export const ERROR_39 = 'Response status is not OK. Status: %s. URL: %s. Message: %s'; -export const ERROR_API_KEY = 'Factory instantiation: %s, api_key must be a non-empty string'; +export const ERROR_0 = 300; +export const ERROR_2 = 302; +export const ERROR_3 = 303; +export const ERROR_4 = 304; +export const ERROR_5 = 305; +export const ERROR_7 = 307; +export const ERROR_9 = 309; +export const ERROR_10 = 310; +export const ERROR_11 = 311; +export const ERROR_12 = 312; +export const ERROR_13 = 313; +export const ERROR_14 = 314; +export const ERROR_15 = 315; +export const ERROR_16 = 316; +export const ERROR_17 = 317; +export const ERROR_18 = 318; +export const ERROR_19 = 319; +export const ERROR_20 = 320; +export const ERROR_21 = 321; +export const ERROR_22 = 322; +export const ERROR_23 = 323; +export const ERROR_24 = 324; +export const ERROR_25 = 325; +export const ERROR_26 = 326; +export const ERROR_32 = 332; +export const ERROR_33 = 333; +export const ERROR_34 = 334; +export const ERROR_35 = 335; +export const ERROR_36 = 336; +export const ERROR_37 = 337; +export const ERROR_38 = 338; +export const ERROR_39 = 339; +export const ERROR_API_KEY = 340; // node -export const ERROR_1 = 'splitio-client:cleanup => Error with Split graceful shutdown: %s'; -export const ERROR_8 = 'splitio-sync:segment-changes => Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'; -export const ERROR_6 = 'splitio-offline:splits-fetcher => Ignoring entry on YAML since the format is incorrect.'; +export const ERROR_1 = 301; +export const ERROR_8 = 308; +export const ERROR_6 = 306; // commons -export const INFO_0 = 'Split SDK is ready from cache.'; -export const INFO_1 = 'Split SDK is ready.'; -export const INFO_2 = 'splitio-client => Split: %s. Key: %s. Evaluation: %s. Label: %s'; -export const INFO_3 = 'splitio-client => Queueing corresponding impression.'; -export const INFO_4 = 'splitio => New shared client instance created.'; -export const INFO_5 = 'splitio => New Split SDK instance created.'; -export const INFO_6 = 'splitio => Manager instance retrieved.'; -export const INFO_7 = 'splitio-sync:polling-manager => Turning segments data polling %s.'; -export const INFO_8 = 'splitio-sync:polling-manager => Starting polling'; -export const INFO_9 = 'splitio-sync:polling-manager => Stopping polling'; -export const INFO_10 = 'splitio-sync:split-changes => Retrying download of splits #%s. Reason: %s'; -export const INFO_11 = 'splitio-sync:push-manager => Refreshing streaming token in %s seconds.'; -export const INFO_12 = 'splitio-sync:push-manager => Attempting to reconnect in %s seconds.'; -export const INFO_13 = 'splitio-sync:push-manager => Connecting to push streaming.'; -export const INFO_14 = 'splitio-sync:push-manager => Streaming is not available. Switching to polling mode.'; -export const INFO_15 = 'splitio-sync:push-manager => Disconnecting from push streaming.'; -export const INFO_16 = 'splitio-sync:submitters => Flushing full events queue and reseting timer.'; -export const INFO_17 = 'splitio-sync:submitters => Pushing %s %s.'; -export const INFO_18 = 'splitio-sync:sync-manager => Streaming not available. Starting periodic fetch of data.'; -export const INFO_19 = 'splitio-sync:sync-manager => Streaming couldn\'t connect. Continue periodic fetch of data.'; -export const INFO_20 = 'splitio-sync:sync-manager => PUSH (re)connected. Syncing and stopping periodic fetch of data.'; -export const INFO_21 = 'splitio-client:event-tracker => Successfully qeued %s'; +export const INFO_0 = 100; +export const INFO_1 = 101; +export const INFO_2 = 102; +export const INFO_3 = 103; +export const INFO_4 = 104; +export const INFO_5 = 105; +export const INFO_6 = 106; +export const INFO_7 = 107; +export const INFO_8 = 108; +export const INFO_9 = 109; +export const INFO_10 = 110; +export const INFO_11 = 111; +export const INFO_12 = 112; +export const INFO_13 = 113; +export const INFO_14 = 114; +export const INFO_15 = 115; +export const INFO_16 = 116; +export const INFO_17 = 117; +export const INFO_18 = 118; +export const INFO_19 = 119; +export const INFO_20 = 120; +export const INFO_21 = 121; // commons -export const WARN_0 = 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'; -export const WARN_1 = 'splitio-engine:value => Defined attribute [%s], no attributes received.'; -export const WARN_2 = 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'; -export const WARN_4 = 'splitio-sync:my-segments => Retrying download of segments #%s. Reason: %s'; -export const WARN_5 = 'splitio-sync:split-changes => Error while doing fetch of Splits. %s'; -export const WARN_6 = 'splitio-sync:sse-handler => Error parsing SSE error notification: %s'; -export const WARN_7 = 'splitio-sync:sse-handler => Error parsing new SSE message notification: %s'; -export const WARN_8 = 'splitio-sync:push-manager => %sFalling back to polling mode.'; -export const WARN_9 = 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'; -export const WARN_10 = 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'; -export const WARN_11 = 'splitio-client:event-tracker => Failed to queue %s'; -export const WARN_12 = '%s: Property %s is of invalid type. Setting value to null.'; -export const WARN_13 = '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'; -export const WARN_14 = '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'; -export const WARN_15 = '%s: %s "%s" is not of type string, converting.'; -export const WARN_17 = '%s: %s "%s" has extra whitespace, trimming.'; -export const WARN_18 = '%s: you passed "%s" that does not exist in this environment, please double check what Splits exist in the web console.'; -export const WARN_19 = '%s: traffic_type_name should be all lowercase - converting string to lowercase.'; -export const WARN_20 = '%s: Traffic Type %s does not have any corresponding Splits in this environment, make sure you\'re tracking your events to a valid traffic type defined in the Split console.'; -export const WARN_21 = 'splitio-settings => %s integration %s at settings %s invalid. %s'; -export const WARN_22 = 'Factory instantiation: split filters have been configured but will have no effect if mode is not \'%s\', since synchronization is being deferred to an external tool.'; -export const WARN_23 = 'Factory instantiation: split filter at position \'%s\' is invalid. It must be an object with a valid filter type (\'byName\' or \'byPrefix\') and a list of \'values\'.'; -export const WARN_24 = 'Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'; -export const WARN_25 = 'splitio-settings => The provided storage is invalid. Fallbacking into default MEMORY storage'; -export const WARN_API_KEY = 'Factory instantiation: %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'; +export const WARN_0 = 200; +export const WARN_1 = 201; +export const WARN_2 = 202; +export const WARN_4 = 204; +export const WARN_5 = 205; +export const WARN_6 = 206; +export const WARN_7 = 207; +export const WARN_8 = 208; +export const WARN_9 = 209; +export const WARN_10 = 210; +export const WARN_11 = 211; +export const WARN_12 = 212; +export const WARN_13 = 213; +export const WARN_14 = 214; +export const WARN_15 = 215; +export const WARN_17 = 217; +export const WARN_18 = 218; +export const WARN_19 = 219; +export const WARN_20 = 220; +export const WARN_21 = 221; +export const WARN_22 = 222; +export const WARN_23 = 223; +export const WARN_24 = 224; +export const WARN_25 = 225; +export const WARN_API_KEY = 226; // node -export const WARN_3 = 'splitio-offline:splits-fetcher => .split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'; +export const WARN_3 = 203; diff --git a/src/logger/index.ts b/src/logger/index.ts index 5513fb39..27b43ab0 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -2,6 +2,7 @@ import objectAssign from 'object-assign'; import { ILoggerOptions, ILogger } from './types'; import { find } from '../utils/lang'; import { LogLevel } from '../types'; +import { IMap, _Map } from '../utils/lang/maps'; export const LogLevels: { [level: string]: LogLevel } = { DEBUG: 'DEBUG', @@ -31,36 +32,42 @@ export class Logger implements ILogger { private category: string; private options: Required; + private codes: IMap; - constructor(category: string, options?: ILoggerOptions) { + constructor(category: string, options?: ILoggerOptions, codes?: IMap) { this.category = category; this.options = objectAssign({}, defaultOptions, options); + this.codes = codes || new _Map(); } setLogLevel(logLevel: LogLevel) { this.options.logLevel = logLevel; } - debug(msg: string, args?: any[]) { + debug(msg: string | number, args?: any[]) { this._log(LogLevels.DEBUG, msg, args); } - info(msg: string, args?: any[]) { + info(msg: string | number, args?: any[]) { this._log(LogLevels.INFO, msg, args); } - warn(msg: string, args?: any[]) { + warn(msg: string | number, args?: any[]) { this._log(LogLevels.WARN, msg, args); } - error(msg: string, args?: any[]) { + error(msg: string | number, args?: any[]) { this._log(LogLevels.ERROR, msg, args); } - private _log(level: LogLevel, text: string, args?: any[]) { + private _log(level: LogLevel, msg: string | number, args?: any[]) { if (this._shouldLog(level)) { - if (args) text = sprintf(text, args); - const formattedText = this._generateLogMessage(level, text); + if (typeof msg === 'number') { + const format = this.codes.get(msg); + if (format) msg = sprintf(format, args); + else msg = `Message code ${msg}${args ? ', with args: ' + args.toString() : ''}`; + } + const formattedText = this._generateLogMessage(level, msg); console.log(formattedText); } diff --git a/src/logger/messages/debug.ts b/src/logger/messages/debug.ts new file mode 100644 index 00000000..dec2f5b7 --- /dev/null +++ b/src/logger/messages/debug.ts @@ -0,0 +1,44 @@ +import { DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_31, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_51 } from '../constants'; + +export const codesDebug: [number, string][] = [ + [DEBUG_0, 'splitio-engine:combiner => [andCombiner] evaluates to %s'], + [DEBUG_1, 'splitio-engine:combiner => Treatment found: %s'], + [DEBUG_2, 'splitio-engine:combiner => All predicates evaluated, no treatment found.'], + [DEBUG_3, 'splitio-engine => [engine] using algo "murmur" bucket %s for key %s using seed %s - treatment %s'], + [DEBUG_4, 'splitio-engine:matcher => [allMatcher] is always true'], + [DEBUG_5, 'splitio-engine:matcher => [betweenMatcher] is %s between %s and %s? %s'], + [DEBUG_6, 'splitio-engine:matcher => [booleanMatcher] %s === %s'], + [DEBUG_7, 'splitio-engine:matcher => [containsAllMatcher] %s contains all elements of %s? %s'], + [DEBUG_8, 'splitio-engine:matcher => [containsAnyMatcher] %s contains at least an element of %s? %s'], + [DEBUG_9, 'splitio-engine:matcher => [containsStringMatcher] %s contains %s? %s'], + [DEBUG_10, 'splitio-engine:matcher => [dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], + [DEBUG_11, 'splitio-engine:matcher => [dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], + [DEBUG_12, 'splitio-engine:matcher => [equalToMatcher] is %s equal to %s? %s'], + [DEBUG_13, 'splitio-engine:matcher => [equalToSetMatcher] is %s equal to set %s? %s'], + [DEBUG_14, 'splitio-engine:matcher => [endsWithMatcher] %s ends with %s? %s'], + [DEBUG_15, 'splitio-engine:matcher => [greaterThanEqualMatcher] is %s greater than %s? %s'], + [DEBUG_16, 'splitio-engine:matcher => [lessThanEqualMatcher] is %s less than %s? %s'], + [DEBUG_17, 'splitio-engine:matcher => [partOfMatcher] %s is part of %s? %s'], + [DEBUG_18, 'splitio-engine:matcher => [asyncSegmentMatcher] evaluated %s / %s => %s'], + [DEBUG_19, 'splitio-engine:matcher => [segmentMatcher] evaluated %s / %s => %s'], + [DEBUG_20, 'splitio-engine:matcher => [stringMatcher] does %s matches with %s? %s'], + [DEBUG_21, 'splitio-engine:matcher => [stringMatcher] %s is an invalid regex'], + [DEBUG_22, 'splitio-engine:matcher => [startsWithMatcher] %s starts with %s? %s'], + [DEBUG_23, 'splitio-engine:matcher => [whitelistMatcher] evaluated %s in [%s] => %s'], + [DEBUG_24, 'splitio-engine:value => Extracted attribute [%s], [%s] will be used for matching.'], + [DEBUG_25, 'splitio-engine:sanitize => Attempted to sanitize [%s] which should be of type [%s]. \n Sanitized and processed value => [%s]'], + [DEBUG_31, 'splitio => Retrieving SDK client.'], + [DEBUG_32, 'splitio => Retrieving default SDK client.'], // @TODO remove and use 'splitio => Retrieving SDK client.' + [DEBUG_33, 'splitio => Retrieving existing SDK client.'], + [DEBUG_36, 'splitio-producer:offline => Splits data: '], + [DEBUG_42, 'splitio-sync:split-changes => Spin up split update using since = %s'], + [DEBUG_43, 'splitio-sync:split-changes => New splits %s'], + [DEBUG_44, 'splitio-sync:split-changes => Removed splits %s'], + [DEBUG_45, 'splitio-sync:split-changes => Segment names collected %s'], + [DEBUG_46, 'splitio-sync:sse-handler => New SSE message received, with data: %s.'], + [DEBUG_47, 'splitio-sync:task => Starting %s. Running each %s millis'], + [DEBUG_48, 'splitio-sync:task => Running %s'], + [DEBUG_49, 'splitio-sync:task => Stopping %s'], + [DEBUG_50, 'splitio-client:impressions-tracker => Successfully stored %s impression%s.'], + [DEBUG_51, 'Factory instantiation: splits filtering criteria is "%s".'] +]; diff --git a/src/logger/messages/debugBrowser.ts b/src/logger/messages/debugBrowser.ts new file mode 100644 index 00000000..86732fcf --- /dev/null +++ b/src/logger/messages/debugBrowser.ts @@ -0,0 +1,6 @@ +import { DEBUG_26, DEBUG_27 } from '../constants'; + +export const codesDebugBrowser: [number, string][] = [ + [DEBUG_26, 'splitio-client:cleanup => Registering flush handler when unload page event is triggered.'], + [DEBUG_27, 'splitio-client:cleanup => Deregistering flush handler when unload page event is triggered.'], +]; diff --git a/src/logger/messages/debugNode.ts b/src/logger/messages/debugNode.ts new file mode 100644 index 00000000..9bb08f6b --- /dev/null +++ b/src/logger/messages/debugNode.ts @@ -0,0 +1,14 @@ +import { DEBUG_28, DEBUG_29, DEBUG_30, DEBUG_39, DEBUG_40, DEBUG_41, DEBUG_34, DEBUG_35, DEBUG_37, DEBUG_38 } from '../constants'; + +export const codesDebugNode: [number, string][] = [ + [DEBUG_28, 'splitio-client:cleanup => Registering cleanup handlers.'], + [DEBUG_29, 'splitio-client:cleanup => Deregistering cleanup handlers.'], + [DEBUG_30, 'splitio-client:cleanup => Split SDK graceful shutdown after SIGTERM.'], + [DEBUG_39, 'splitio-sync:segment-changes => Processed %s with till = %s. Added: %s. Removed: %s'], + [DEBUG_40, 'splitio-sync:segment-changes => Processing segment %s'], + [DEBUG_41, 'splitio-sync:segment-changes => Started segments update'], + [DEBUG_34, 'splitio-offline:splits-fetcher => Ignoring empty line or comment at #%s'], + [DEBUG_35, 'splitio-offline:splits-fetcher => Ignoring line since it does not have exactly two columns #%s'], + [DEBUG_37, 'splitio-sync:polling-manager => Splits will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? + [DEBUG_38, 'splitio-sync:polling-manager => Segments will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? +]; diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts new file mode 100644 index 00000000..9c2cbf1f --- /dev/null +++ b/src/logger/messages/error.ts @@ -0,0 +1,37 @@ +import { ERROR_0, ERROR_2, ERROR_3, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_13, ERROR_14, ERROR_15, ERROR_16, ERROR_17, ERROR_18, ERROR_19, ERROR_20, ERROR_21, ERROR_22, ERROR_23, ERROR_24, ERROR_25, ERROR_26, ERROR_32, ERROR_33, ERROR_34, ERROR_35, ERROR_36, ERROR_37, ERROR_38, ERROR_39, ERROR_API_KEY } from '../constants'; + +export const codesError: [number, string][] = [ + [ERROR_0, 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'], + [ERROR_2, 'splitio-utils:logger => Invalid Log Level - No changes to the logs will be applied.'], + [ERROR_3, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], + [ERROR_4, 'splitio => Manager instance is not available. Provide the manager module on settings.'], + [ERROR_5, 'splitio-services:service => %s The SDK will not get ready.'], + [ERROR_7, 'splitio-producer:offline => There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], + [ERROR_9, 'splitio-sync:sse-handler => Fail to connect to streaming, with error message: %s'], + [ERROR_10, 'splitio-sync:push-manager => Failed to authenticate for streaming. Error: "%s".'], + [ERROR_11, 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'], + [ERROR_12, 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'], + [ERROR_13, '%s: attributes must be a plain object.'], + [ERROR_14, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], + [ERROR_15, '%s: you passed a null or undefined event_type, event_type must be a non-empty string.'], + [ERROR_16, '%s: you passed an invalid event_type, event_type must be a non-empty string.'], + [ERROR_17, '%s: you passed an empty event_type, event_type must be a non-empty string.'], + [ERROR_18, '%s: properties must be a plain object.'], + [ERROR_19, '%s: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'], + [ERROR_20, '%s: value must be a finite number.'], + [ERROR_21, 'Client has already been destroyed - no calls possible.'], + [ERROR_22, '%s: you passed a null or undefined %s, %s must be a non-empty string.'], + [ERROR_23, '%s: %s too long, %s must be 250 characters or less.'], + [ERROR_24, '%s: you passed an invalid %s type, %s must be a non-empty string.'], + [ERROR_25, '%s: you passed an empty string, %s must be a non-empty string.'], + [ERROR_26, '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'], + [ERROR_32, '%s: you passed an invalid %s, %s must be a non-empty string.'], + [ERROR_33, '%s: you passed an empty %s, %s must be a non-empty string.'], + [ERROR_34, '%s: %s must be a non-empty array.'], + [ERROR_35, '%s: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.'], + [ERROR_36, '%s: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.'], + [ERROR_37, '%s: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.'], + [ERROR_38, 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: "%s" or "%s". Defaulting to "%s" mode.'], + [ERROR_39, 'Response status is not OK. Status: %s. URL: %s. Message: %s'], + [ERROR_API_KEY, 'Factory instantiation: %s, api_key must be a non-empty string'] +]; diff --git a/src/logger/messages/errorNode.ts b/src/logger/messages/errorNode.ts new file mode 100644 index 00000000..8e3adc6d --- /dev/null +++ b/src/logger/messages/errorNode.ts @@ -0,0 +1,7 @@ +import { ERROR_1, ERROR_8, ERROR_6 } from '../constants'; + +export const codesErrorNode: [number, string][] = [ + [ERROR_1, 'splitio-client:cleanup => Error with Split graceful shutdown: %s'], + [ERROR_8, 'splitio-sync:segment-changes => Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'], + [ERROR_6, 'splitio-offline:splits-fetcher => Ignoring entry on YAML since the format is incorrect.'], +]; diff --git a/src/logger/messages/info.ts b/src/logger/messages/info.ts new file mode 100644 index 00000000..e2fed1a3 --- /dev/null +++ b/src/logger/messages/info.ts @@ -0,0 +1,26 @@ +import { INFO_0, INFO_1, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21 } from '../constants'; + +export const codesInfo: [number, string][] = [ + [INFO_0, 'Split SDK is ready from cache.'], + [INFO_1, 'Split SDK is ready.'], + [INFO_2, 'splitio-client => Split: %s. Key: %s. Evaluation: %s. Label: %s'], + [INFO_3, 'splitio-client => Queueing corresponding impression.'], + [INFO_4, 'splitio => New shared client instance created.'], + [INFO_5, 'splitio => New Split SDK instance created.'], + [INFO_6, 'splitio => Manager instance retrieved.'], + [INFO_7, 'splitio-sync:polling-manager => Turning segments data polling %s.'], + [INFO_8, 'splitio-sync:polling-manager => Starting polling'], + [INFO_9, 'splitio-sync:polling-manager => Stopping polling'], + [INFO_10, 'splitio-sync:split-changes => Retrying download of splits #%s. Reason: %s'], + [INFO_11, 'splitio-sync:push-manager => Refreshing streaming token in %s seconds.'], + [INFO_12, 'splitio-sync:push-manager => Attempting to reconnect in %s seconds.'], + [INFO_13, 'splitio-sync:push-manager => Connecting to push streaming.'], + [INFO_14, 'splitio-sync:push-manager => Streaming is not available. Switching to polling mode.'], + [INFO_15, 'splitio-sync:push-manager => Disconnecting from push streaming.'], + [INFO_16, 'splitio-sync:submitters => Flushing full events queue and reseting timer.'], + [INFO_17, 'splitio-sync:submitters => Pushing %s %s.'], + [INFO_18, 'splitio-sync:sync-manager => Streaming not available. Starting periodic fetch of data.'], + [INFO_19, 'splitio-sync:sync-manager => Streaming couldn\'t connect. Continue periodic fetch of data.'], + [INFO_20, 'splitio-sync:sync-manager => PUSH (re)connected. Syncing and stopping periodic fetch of data.'], + [INFO_21, 'splitio-client:event-tracker => Successfully qeued %s'] +]; diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts new file mode 100644 index 00000000..8e4bca72 --- /dev/null +++ b/src/logger/messages/warn.ts @@ -0,0 +1,29 @@ +import { WARN_0, WARN_1, WARN_2, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_12, WARN_13, WARN_14, WARN_15, WARN_17, WARN_18, WARN_19, WARN_20, WARN_21, WARN_22, WARN_23, WARN_24, WARN_25, WARN_API_KEY } from '../constants'; + +export const codesWarn: [number, string][] = [ + [WARN_0, 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'], + [WARN_1, 'splitio-engine:value => Defined attribute [%s], no attributes received.'], + [WARN_2, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], + [WARN_4, 'splitio-sync:my-segments => Retrying download of segments #%s. Reason: %s'], + [WARN_5, 'splitio-sync:split-changes => Error while doing fetch of Splits. %s'], + [WARN_6, 'splitio-sync:sse-handler => Error parsing SSE error notification: %s'], + [WARN_7, 'splitio-sync:sse-handler => Error parsing new SSE message notification: %s'], + [WARN_8, 'splitio-sync:push-manager => %sFalling back to polling mode.'], + [WARN_9, 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'], + [WARN_10, 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'], + [WARN_11, 'splitio-client:event-tracker => Failed to queue %s'], + [WARN_12, '%s: Property %s is of invalid type. Setting value to null.'], + [WARN_13, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], + [WARN_14, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], + [WARN_15, '%s: %s "%s" is not of type string, converting.'], + [WARN_17, '%s: %s "%s" has extra whitespace, trimming.'], + [WARN_18, '%s: you passed "%s" that does not exist in this environment, please double check what Splits exist in the web console.'], + [WARN_19, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], + [WARN_20, '%s: Traffic Type %s does not have any corresponding Splits in this environment, make sure you\'re tracking your events to a valid traffic type defined in the Split console.'], + [WARN_21, 'splitio-settings => %s integration %s at settings %s invalid. %s'], + [WARN_22, 'Factory instantiation: split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'], + [WARN_23, 'Factory instantiation: split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'], + [WARN_24, 'Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'], + [WARN_25, 'splitio-settings => The provided storage is invalid. Fallbacking into default MEMORY storage'], + [WARN_API_KEY, 'Factory instantiation: %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'] +]; diff --git a/src/logger/messages/warnNode.ts b/src/logger/messages/warnNode.ts new file mode 100644 index 00000000..12d1724f --- /dev/null +++ b/src/logger/messages/warnNode.ts @@ -0,0 +1,5 @@ +import { WARN_3 } from '../constants'; + +export const codesWarnNode: [number, string][] = [ + [WARN_3, 'splitio-offline:splits-fetcher => .split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'], +]; diff --git a/src/logger/types.ts b/src/logger/types.ts index 5fa1d2c4..d691d255 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -8,11 +8,11 @@ export interface ILoggerOptions { export interface ILogger { setLogLevel(logLevel: LogLevel): void - debug(msg: string, args?: any[]): void + debug(msg: string | number, args?: any[]): void - info(msg: string, args?: any[]): void + info(msg: string | number, args?: any[]): void - warn(msg: string, args?: any[]): void + warn(msg: string | number, args?: any[]): void - error(msg: string, args?: any[]): void + error(msg: string | number, args?: any[]): void } diff --git a/src/utils/inputValidation/__tests__/attributes.spec.ts b/src/utils/inputValidation/__tests__/attributes.spec.ts index c91310b4..e7ae5e0d 100644 --- a/src/utils/inputValidation/__tests__/attributes.spec.ts +++ b/src/utils/inputValidation/__tests__/attributes.spec.ts @@ -1,3 +1,4 @@ +import { ERROR_13 } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateAttributes } from '../attributes'; @@ -40,7 +41,7 @@ describe('INPUT VALIDATION for Attributes', () => { const invalidAttribute = invalidAttributes[i]; expect(validateAttributes(loggerMock, invalidAttribute, 'test_method')).toBe(false); // Invalid attribute objects should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual('test_method: attributes must be a plain object.'); // The error should be logged for the invalid attributes map. + expect(loggerMock.error).lastCalledWith(ERROR_13, ['test_method']); // The error should be logged for the invalid attributes map. loggerMock.error.mockClear(); } diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index 51a993e3..b5f108cf 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -3,6 +3,7 @@ import { ILogger } from '../../../logger/types'; import { LogLevel } from '../../../types'; import { isLocalStorageAvailable } from '../../env/isLocalStorageAvailable'; import { isNode } from '../../env/isNode'; +import { IMap } from '../../lang/maps'; // @TODO when integrating with other packages, find the best way to handle initial state per environment const LS_KEY = 'splitio_debug'; @@ -47,21 +48,25 @@ export function getLogLevel(debugValue: unknown): LogLevel | undefined { } /** - * Validates the `debug` property at config and use it to set the log level. - * - * @param settings user config object - * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. + * Factory of logger validator, which validates the `debug` property at config and creates a logger instance with the provided `debug` log level. */ -export function validateLogger(settings: { debug: unknown} ): ILogger { +export function validateLoggerFactory(msgCodes?: IMap) { - const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; + /** + * Validates the `debug` property at config and use it to set the log level. + * + * @param settings user config object + * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. + */ + return function validateLogger(settings: { debug: unknown }): ILogger { - const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }); + const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; - // logs error if the provided settings debug value is invalid - if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); - - return log; -} + const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }, msgCodes); + // logs error if the provided settings debug value is invalid + if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); + return log; + }; +} diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index 8e01d90c..4d36e3a3 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -1,31 +1,27 @@ +import { Logger } from '../../../logger'; import { ILogger } from '../../../logger/types'; -const noopLogger: ILogger = { - setLogLevel() { }, - debug() { }, - info() { }, - warn() { }, - error() { } -}; - function isLogger(log: any): log is ILogger { return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function' && typeof log.setLogLevel === 'function'; } /** - * Validates the `log` (logger) property at config. + * Validates the `debug` (logger) property at config. * * @param settings user config object - * @returns the provided logger or a no-op logger if no one is provided - * @throws throws an error if a logger was provided but is invalid + * @returns the provided logger at `settings.debug` or a new one with NONE log level if invalid or not provided */ export function validateLogger(settings: { debug: unknown }): ILogger { const { debug } = settings; + const log = new Logger('splitio', { logLevel: 'NONE' }); - if (!debug) return noopLogger; + // @TODO consider debug of boolean or string types + if (!debug) return log; if (isLogger(debug)) return debug; - // @TODO log error instead of throwing one - throw new Error('The provided `debug` value at config is not valid'); + // logs error, for consistency with builtin logger validator + log.error('The provided `debug` value at config is invalid.'); + + return log; } From b55611988108ff4082e83f6862b24edbf7f8ea1e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 16 Mar 2021 17:14:38 -0300 Subject: [PATCH 34/58] removed unused comments --- src/evaluator/combiners/and.ts | 2 -- src/evaluator/combiners/ifelseif.ts | 2 -- src/evaluator/condition/engineUtils.ts | 2 -- src/evaluator/matchers/all.ts | 2 -- src/evaluator/matchers/between.ts | 2 -- src/evaluator/matchers/boolean.ts | 2 -- src/evaluator/matchers/cont_all.ts | 2 -- src/evaluator/matchers/cont_any.ts | 2 -- src/evaluator/matchers/cont_str.ts | 2 -- src/evaluator/matchers/dependency.ts | 2 -- src/evaluator/matchers/eq.ts | 2 -- src/evaluator/matchers/eq_set.ts | 2 -- src/evaluator/matchers/ew.ts | 2 -- src/evaluator/matchers/gte.ts | 2 -- src/evaluator/matchers/lte.ts | 2 -- src/evaluator/matchers/part_of.ts | 2 -- src/evaluator/matchers/segment.ts | 2 -- src/evaluator/matchers/string.ts | 2 -- src/evaluator/matchers/sw.ts | 2 -- src/evaluator/matchers/whitelist.ts | 2 -- src/evaluator/value/index.ts | 2 -- src/evaluator/value/sanitize.ts | 2 -- src/listeners/browser.ts | 3 --- src/listeners/node.ts | 2 -- src/readiness/sdkReadinessManager.ts | 2 -- src/sdkClient/client.ts | 2 -- src/sdkClient/sdkClientMethod.ts | 2 -- src/sdkClient/sdkClientMethodCS.ts | 2 -- src/sdkClient/sdkClientMethodCSWithTT.ts | 2 -- src/sdkFactory/index.ts | 2 -- src/services/splitHttpClient.ts | 2 -- src/sync/offline/splitsParser/splitsParserFromFile.ts | 2 -- src/sync/offline/syncTasks/fromObjectSyncTask.ts | 2 -- src/sync/polling/pollingManagerCS.ts | 2 -- src/sync/polling/pollingManagerSS.ts | 2 -- src/sync/polling/syncTasks/mySegmentsSyncTask.ts | 2 -- src/sync/polling/syncTasks/segmentsSyncTask.ts | 2 -- src/sync/polling/syncTasks/splitsSyncTask.ts | 2 -- src/sync/streaming/SSEHandler/index.ts | 2 -- src/sync/streaming/pushManager.ts | 2 -- src/sync/streaming/pushManagerCS.ts | 2 -- src/sync/streaming/pushManagerSS.ts | 2 -- src/sync/submitters/eventsSyncTask.ts | 2 -- src/sync/submitters/submitterSyncTask.ts | 2 -- src/sync/syncTask.ts | 2 -- src/trackers/eventTracker.ts | 2 -- src/trackers/impressionsTracker.ts | 2 -- src/utils/inputValidation/apiKey.ts | 2 -- src/utils/inputValidation/attributes.ts | 2 -- src/utils/inputValidation/event.ts | 2 -- src/utils/inputValidation/eventProperties.ts | 2 -- src/utils/inputValidation/eventValue.ts | 2 -- src/utils/inputValidation/isOperational.ts | 2 -- src/utils/inputValidation/key.ts | 2 -- src/utils/inputValidation/preloadedData.ts | 2 -- src/utils/inputValidation/split.ts | 2 -- src/utils/inputValidation/splitExistance.ts | 2 -- src/utils/inputValidation/splits.ts | 2 -- src/utils/inputValidation/trafficType.ts | 2 -- src/utils/inputValidation/trafficTypeExistance.ts | 2 -- src/utils/settingsValidation/impressionsMode.ts | 2 -- src/utils/settingsValidation/integrations/common.ts | 2 -- src/utils/settingsValidation/integrations/configurable.ts | 2 +- src/utils/settingsValidation/splitFilters.ts | 2 -- src/utils/settingsValidation/storage/storageCS.ts | 2 -- 65 files changed, 1 insertion(+), 130 deletions(-) diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index f21653d2..b2981f29 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -1,6 +1,4 @@ import { findIndex } from '../../utils/lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:combiner'); import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { MaybeThenable } from '../../dtos/types'; diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index 0f2f202a..cf3bf834 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -1,6 +1,4 @@ import { findIndex } from '../../utils/lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:combiner'); import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import * as LabelsConstants from '../../utils/labels'; diff --git a/src/evaluator/condition/engineUtils.ts b/src/evaluator/condition/engineUtils.ts index b8b842de..ab4c8fac 100644 --- a/src/evaluator/condition/engineUtils.ts +++ b/src/evaluator/condition/engineUtils.ts @@ -1,8 +1,6 @@ import { DEBUG_3 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { bucket } from '../../utils/murmur3/murmur3'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine'); /** * Get the treatment name given a key, a seed, and the percentage of each treatment. diff --git a/src/evaluator/matchers/all.ts b/src/evaluator/matchers/all.ts index df609cab..5eb43000 100644 --- a/src/evaluator/matchers/all.ts +++ b/src/evaluator/matchers/all.ts @@ -1,6 +1,4 @@ import { DEBUG_4 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; export default function allMatcherContext(log: ILogger) { diff --git a/src/evaluator/matchers/between.ts b/src/evaluator/matchers/between.ts index cd40a24d..46c123dd 100644 --- a/src/evaluator/matchers/between.ts +++ b/src/evaluator/matchers/between.ts @@ -1,7 +1,5 @@ import { IBetweenMatcherData } from '../../dtos/types'; import { DEBUG_5 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; export default function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatcherData) /*: Function */ { diff --git a/src/evaluator/matchers/boolean.ts b/src/evaluator/matchers/boolean.ts index 74bfd378..87281534 100644 --- a/src/evaluator/matchers/boolean.ts +++ b/src/evaluator/matchers/boolean.ts @@ -1,6 +1,4 @@ import { DEBUG_6 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; export default function booleanMatcherContext(log: ILogger, ruleAttr: boolean) /*: Function */ { diff --git a/src/evaluator/matchers/cont_all.ts b/src/evaluator/matchers/cont_all.ts index 5c2a4289..3e7f3d4b 100644 --- a/src/evaluator/matchers/cont_all.ts +++ b/src/evaluator/matchers/cont_all.ts @@ -1,6 +1,4 @@ import { DEBUG_7 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; diff --git a/src/evaluator/matchers/cont_any.ts b/src/evaluator/matchers/cont_any.ts index beaa3b2b..68565478 100644 --- a/src/evaluator/matchers/cont_any.ts +++ b/src/evaluator/matchers/cont_any.ts @@ -1,6 +1,4 @@ import { DEBUG_8 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; diff --git a/src/evaluator/matchers/cont_str.ts b/src/evaluator/matchers/cont_str.ts index a126932f..2438d390 100644 --- a/src/evaluator/matchers/cont_str.ts +++ b/src/evaluator/matchers/cont_str.ts @@ -1,6 +1,4 @@ import { isString } from '../../utils/lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import { DEBUG_9 } from '../../logger/constants'; diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index 4795b61f..f5399024 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -1,7 +1,5 @@ import { IDependencyMatcherData, MaybeThenable } from '../../dtos/types'; import { IStorageAsync, IStorageSync } from '../../storages/types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { IDependencyMatcherValue, IEvaluation, ISplitEvaluator } from '../types'; diff --git a/src/evaluator/matchers/eq.ts b/src/evaluator/matchers/eq.ts index ef74e56e..724b647d 100644 --- a/src/evaluator/matchers/eq.ts +++ b/src/evaluator/matchers/eq.ts @@ -1,6 +1,4 @@ import { DEBUG_12 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; export default function equalToMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ { diff --git a/src/evaluator/matchers/eq_set.ts b/src/evaluator/matchers/eq_set.ts index d552a2d5..9f920e8a 100644 --- a/src/evaluator/matchers/eq_set.ts +++ b/src/evaluator/matchers/eq_set.ts @@ -1,6 +1,4 @@ import { DEBUG_13 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; diff --git a/src/evaluator/matchers/ew.ts b/src/evaluator/matchers/ew.ts index 2d94d4b2..a956e133 100644 --- a/src/evaluator/matchers/ew.ts +++ b/src/evaluator/matchers/ew.ts @@ -1,6 +1,4 @@ import { DEBUG_14 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import { endsWith as strEndsWith } from '../../utils/lang'; diff --git a/src/evaluator/matchers/gte.ts b/src/evaluator/matchers/gte.ts index dd5b4abf..10e73066 100644 --- a/src/evaluator/matchers/gte.ts +++ b/src/evaluator/matchers/gte.ts @@ -1,6 +1,4 @@ import { DEBUG_15 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; export default function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ { diff --git a/src/evaluator/matchers/lte.ts b/src/evaluator/matchers/lte.ts index d3804088..b594b890 100644 --- a/src/evaluator/matchers/lte.ts +++ b/src/evaluator/matchers/lte.ts @@ -1,6 +1,4 @@ import { DEBUG_16 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; export default function lessThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: function */ { diff --git a/src/evaluator/matchers/part_of.ts b/src/evaluator/matchers/part_of.ts index 7b804144..4b410e99 100644 --- a/src/evaluator/matchers/part_of.ts +++ b/src/evaluator/matchers/part_of.ts @@ -1,6 +1,4 @@ import { findIndex } from '../../utils/lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import { DEBUG_17 } from '../../logger/constants'; diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index 23efc8de..9f197e0e 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -1,7 +1,5 @@ import { MaybeThenable } from '../../dtos/types'; import { ISegmentsCacheBase } from '../../storages/types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { DEBUG_18, DEBUG_19 } from '../../logger/constants'; diff --git a/src/evaluator/matchers/string.ts b/src/evaluator/matchers/string.ts index c8353323..dff34f8d 100644 --- a/src/evaluator/matchers/string.ts +++ b/src/evaluator/matchers/string.ts @@ -1,6 +1,4 @@ import { DEBUG_21, DEBUG_20 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; export default function stringMatcherContext(log: ILogger, ruleAttr: string) /*: Function */ { diff --git a/src/evaluator/matchers/sw.ts b/src/evaluator/matchers/sw.ts index 082b9ab8..f2907c4d 100644 --- a/src/evaluator/matchers/sw.ts +++ b/src/evaluator/matchers/sw.ts @@ -1,6 +1,4 @@ import { DEBUG_22 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import { startsWith } from '../../utils/lang'; diff --git a/src/evaluator/matchers/whitelist.ts b/src/evaluator/matchers/whitelist.ts index 0da714de..142be8ad 100644 --- a/src/evaluator/matchers/whitelist.ts +++ b/src/evaluator/matchers/whitelist.ts @@ -1,6 +1,4 @@ import { setToArray, ISet } from '../../utils/lang/sets'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:matcher'); import { ILogger } from '../../logger/types'; import { DEBUG_23 } from '../../logger/constants'; diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index eae699e4..a7245066 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -1,7 +1,5 @@ import { SplitIO } from '../../types'; import { IMatcherDto } from '../types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:value'); import { ILogger } from '../../logger/types'; import sanitizeValue from './sanitize'; import { DEBUG_24, WARN_1, WARN_0 } from '../../logger/constants'; diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index a05e023f..bbc945f1 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -1,7 +1,5 @@ import { SplitIO } from '../../types'; import { IDependencyMatcherValue } from '../types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-engine:sanitize'); import { ILogger } from '../../logger/types'; import { isObject, uniq, toString, toNumber } from '../../utils/lang'; import { zeroSinceHH, zeroSinceSS } from '../convertions'; diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index 78a2b1a1..32f36130 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -12,9 +12,6 @@ import { OPTIMIZED, DEBUG } from '../utils/constants'; import objectAssign from 'object-assign'; import { DEBUG_26, DEBUG_27 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio-client:cleanup'); - // 'unload' event is used instead of 'beforeunload', since 'unload' is not a cancelable event, so no other listeners can stop the event from occurring. const UNLOAD_DOM_EVENT = 'unload'; diff --git a/src/listeners/node.ts b/src/listeners/node.ts index e61e918a..35d8f0e9 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -4,8 +4,6 @@ import thenable from '../utils/promise/thenable'; import { MaybeThenable } from '../dtos/types'; import { ISettings } from '../types'; import { DEBUG_28, DEBUG_29, DEBUG_30, ERROR_1 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio-client:cleanup'); /** * We'll listen for SIGTERM since it's the standard signal for server shutdown. diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index 97cfd482..d2bfffe7 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -6,8 +6,6 @@ import { IEventEmitter } from '../types'; import { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from './constants'; import { ILogger } from '../logger/types'; import { ERROR_3, INFO_0, INFO_1, WARN_2 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory(''); const NEW_LISTENER_EVENT = 'newListener'; const REMOVE_LISTENER_EVENT = 'removeListener'; diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index 101faa3b..0dfd6dd9 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -9,8 +9,6 @@ import { IClientFactoryParams } from './types'; import { IEvaluationResult } from '../evaluator/types'; import { SplitIO, ImpressionDTO } from '../types'; import { INFO_2, INFO_3 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio-client'); /** diff --git a/src/sdkClient/sdkClientMethod.ts b/src/sdkClient/sdkClientMethod.ts index 4e200b49..f9615650 100644 --- a/src/sdkClient/sdkClientMethod.ts +++ b/src/sdkClient/sdkClientMethod.ts @@ -2,8 +2,6 @@ import { ISdkClientFactoryParams } from './types'; import { SplitIO } from '../types'; import { sdkClientFactory } from './sdkClient'; import { DEBUG_31 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio'); /** * Factory of client method for server-side SDKs (ISDK and IAsyncSDK) diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index fc8a9da5..c50c3986 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -8,8 +8,6 @@ import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio'); function buildInstanceId(key: SplitIO.SplitKey) { // @ts-ignore diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index 9145ec0e..03f9caac 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -9,8 +9,6 @@ import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio'); function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string) { // @ts-ignore diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 6490c6f4..4b80cabf 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -11,8 +11,6 @@ import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; import { createLoggerAPI } from '../logger/sdkLogger'; import { INFO_5, INFO_6, ERROR_4 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio'); /** * Modular SDK factory diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index 5edecb41..58a768d4 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -4,8 +4,6 @@ import objectAssign from 'object-assign'; import { IMetadata } from '../dtos/types'; import { ILogger } from '../logger/types'; import { ERROR_39, ERROR_5 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio-services:service'); const messageNoFetch = 'Global fetch API is not available.'; diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index f9cce80f..71dcbaec 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -10,8 +10,6 @@ import { ISplitPartial } from '../../../dtos/types'; import { SplitIO } from '../../../types'; import { ILogger } from '../../../logger/types'; import { DEBUG_34, DEBUG_35, ERROR_6, WARN_3 } from '../../../logger/constants'; -// import { logFactory } from '../../../logger/sdkLogger'; -// const log = logFactory('splitio-offline:splits-fetcher'); type IYamlSplitEntry = Record diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index 0c1f2d14..0ffb2f5a 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -9,8 +9,6 @@ import { ISettings } from '../../../types'; import { CONTROL } from '../../../utils/constants'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { DEBUG_36, ERROR_7 } from '../../../logger/constants'; -// import { logFactory } from '../../../logger/sdkLogger'; -// const log = logFactory('splitio-producer:offline'); /** * Offline equivalent of `splitChangesUpdaterFactory` diff --git a/src/sync/polling/pollingManagerCS.ts b/src/sync/polling/pollingManagerCS.ts index 8eb649ef..3d4687c2 100644 --- a/src/sync/polling/pollingManagerCS.ts +++ b/src/sync/polling/pollingManagerCS.ts @@ -9,8 +9,6 @@ import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants'; import { INFO_7, INFO_8, INFO_9 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:polling-manager'); /** * Expose start / stop mechanism for polling data from services. diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index c8acc0c0..587e25cc 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -8,8 +8,6 @@ import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types'; import thenable from '../../utils/promise/thenable'; import { INFO_8, INFO_9 } from '../../logger/constants'; import { DEBUG_37, DEBUG_38 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:polling-manager'); /** * Expose start / stop mechanism for pulling data from services. diff --git a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts index 4524de09..9bc3aeb8 100644 --- a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts @@ -11,8 +11,6 @@ import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; import { WARN_4 } from '../../../logger/constants'; -// import { logFactory } from '../../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:my-segments'); type IMySegmentsUpdater = (segmentList?: string[], noCache?: boolean) => Promise diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index 7438c804..676d67f2 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -12,8 +12,6 @@ import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; import { DEBUG_41, DEBUG_40, DEBUG_39, ERROR_8 } from '../../../logger/constants'; -// import { logFactory } from '../../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:segment-changes'); type ISegmentChangesUpdater = (segmentNames?: string[], noCache?: boolean, fetchOnlyNew?: boolean) => Promise diff --git a/src/sync/polling/syncTasks/splitsSyncTask.ts b/src/sync/polling/syncTasks/splitsSyncTask.ts index 0b448745..81bd23fc 100644 --- a/src/sync/polling/syncTasks/splitsSyncTask.ts +++ b/src/sync/polling/syncTasks/splitsSyncTask.ts @@ -14,8 +14,6 @@ import { ISettings } from '../../../types'; import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; import { DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, WARN_5, INFO_10 } from '../../../logger/constants'; -// import { logFactory } from '../../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:split-changes'); type ISplitChangesUpdater = (noCache?: boolean) => Promise diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index 504d658c..c1e5d5dc 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -6,8 +6,6 @@ import { ISseEventHandler } from '../SSEClient/types'; import { INotificationError } from './types'; import { ILogger } from '../../../logger/types'; import { WARN_6, ERROR_9, WARN_7, DEBUG_46 } from '../../../logger/constants'; -// import { logFactory } from '../../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:sse-handler'); function isRetryableError(error: INotificationError) { if (error.parsedData && error.parsedData.code) { diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index f10c61fe..a3e9ef22 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -19,8 +19,6 @@ import { getMatching } from '../../utils/key'; import { MY_SEGMENTS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP } from './constants'; import { IPlatform } from '../../sdkFactory/types'; import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:push-manager'); /** * PushManager factory: diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index 2eb32446..9a23a9ab 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -18,8 +18,6 @@ import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { IPlatform } from '../../sdkFactory/types'; import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:push-manager'); /** * PushManager factory for client-side, with support for multiple clients. diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index 7aba9914..138a52e9 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -15,8 +15,6 @@ import SSEClient from './SSEClient'; import { ISettings } from '../../types'; import { IPlatform } from '../../sdkFactory/types'; import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:push-manager'); /** * PushManager factory for server-side diff --git a/src/sync/submitters/eventsSyncTask.ts b/src/sync/submitters/eventsSyncTask.ts index c4f74648..e7024c0c 100644 --- a/src/sync/submitters/eventsSyncTask.ts +++ b/src/sync/submitters/eventsSyncTask.ts @@ -4,8 +4,6 @@ import { ISyncTask, ITimeTracker } from '../types'; import { submitterSyncTaskFactory } from './submitterSyncTask'; import { ILogger } from '../../logger/types'; import { INFO_16 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:submitters'); /** * Sync task that periodically posts tracked events diff --git a/src/sync/submitters/submitterSyncTask.ts b/src/sync/submitters/submitterSyncTask.ts index b025cbf3..da6a9301 100644 --- a/src/sync/submitters/submitterSyncTask.ts +++ b/src/sync/submitters/submitterSyncTask.ts @@ -3,8 +3,6 @@ import { ISyncTask, ITimeTracker } from '../types'; import { IRecorderCacheConsumerSync } from '../../storages/types'; import { ILogger } from '../../logger/types'; import { INFO_17, WARN_9, WARN_10 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-sync:submitters'); /** * Base function to create submitter sync tasks, such as ImpressionsSyncTask and EventsSyncTask diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index 2e2d1fd1..cb63701c 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -1,8 +1,6 @@ import { DEBUG_48, DEBUG_47, DEBUG_49 } from '../logger/constants'; import { ILogger } from '../logger/types'; import { ISyncTask } from './types'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio-sync:task'); /** * factory of sync tasks diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index 9f1dad67..960924dc 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -5,8 +5,6 @@ import { IEventsHandler, IEventTracker } from './types'; import { SplitIO } from '../types'; import { ILogger } from '../logger/types'; import { INFO_21, WARN_11 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio-client:event-tracker'); /** * Event tracker stores events in cache and pass them to the integrations manager if provided. diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index ede9b865..53ec5178 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -8,8 +8,6 @@ import { SplitIO, ImpressionDTO } from '../types'; import { IImpressionObserver } from './impressionObserver/types'; import { ILogger } from '../logger/types'; import { DEBUG_50, ERROR_11, ERROR_12 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// const log = logFactory('splitio-client:impressions-tracker'); /** * Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided. diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index 377058cb..da2bdbbb 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -1,8 +1,6 @@ import { ERROR_API_KEY, WARN_API_KEY } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); /** validates the given api key */ export function validateApiKey(log: ILogger, maybeApiKey: any): string | false { diff --git a/src/utils/inputValidation/attributes.ts b/src/utils/inputValidation/attributes.ts index 45fe4405..d40f21db 100644 --- a/src/utils/inputValidation/attributes.ts +++ b/src/utils/inputValidation/attributes.ts @@ -2,8 +2,6 @@ import { isObject } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; import { ERROR_13 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); export function validateAttributes(log: ILogger, maybeAttrs: any, method: string): SplitIO.Attributes | undefined | false { // Attributes are optional diff --git a/src/utils/inputValidation/event.ts b/src/utils/inputValidation/event.ts index a5d3daff..f067b23e 100644 --- a/src/utils/inputValidation/event.ts +++ b/src/utils/inputValidation/event.ts @@ -1,8 +1,6 @@ import { ERROR_14, ERROR_15, ERROR_16, ERROR_17 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); const EVENT_TYPE_REGEX = /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/; diff --git a/src/utils/inputValidation/eventProperties.ts b/src/utils/inputValidation/eventProperties.ts index caca4be5..6f195e09 100644 --- a/src/utils/inputValidation/eventProperties.ts +++ b/src/utils/inputValidation/eventProperties.ts @@ -2,8 +2,6 @@ import { isObject, shallowClone, isString, isFiniteNumber, isBoolean } from '../ import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; import { ERROR_18, ERROR_19, WARN_12, WARN_13 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); const ECMA_SIZES = { NULL: 0, // While on the JSON it's going to occupy more space, we'll take it as 0 for the approximation. diff --git a/src/utils/inputValidation/eventValue.ts b/src/utils/inputValidation/eventValue.ts index 6d0a4f38..ef9f5c36 100644 --- a/src/utils/inputValidation/eventValue.ts +++ b/src/utils/inputValidation/eventValue.ts @@ -1,8 +1,6 @@ import { ERROR_20 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isFiniteNumber } from '../lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); export function validateEventValue(log: ILogger, maybeValue: any, method: string): number | false { if (isFiniteNumber(maybeValue) || maybeValue == undefined) // eslint-disable-line eqeqeq diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index 6aa2db6d..34ef4464 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -1,8 +1,6 @@ import { ERROR_21, WARN_14 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { IReadinessManager } from '../../readiness/types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadinessManager): boolean { if (!readinessManager.isDestroyed()) return true; diff --git a/src/utils/inputValidation/key.ts b/src/utils/inputValidation/key.ts index 66be37cb..f7ec064f 100644 --- a/src/utils/inputValidation/key.ts +++ b/src/utils/inputValidation/key.ts @@ -2,8 +2,6 @@ import { isObject, isString, isFiniteNumber, toString } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; import { ERROR_22, WARN_15, ERROR_25, ERROR_23, ERROR_24, ERROR_26 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); const KEY_MAX_LENGTH = 250; diff --git a/src/utils/inputValidation/preloadedData.ts b/src/utils/inputValidation/preloadedData.ts index fd1ae877..0b02c6c2 100644 --- a/src/utils/inputValidation/preloadedData.ts +++ b/src/utils/inputValidation/preloadedData.ts @@ -2,8 +2,6 @@ import { isObject, isString, isFiniteNumber } from '../lang'; import { validateSplit } from './split'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); function validateTimestampData(log: ILogger, maybeTimestamp: any, method: string, item: string) { if (isFiniteNumber(maybeTimestamp) && maybeTimestamp > -1) return true; diff --git a/src/utils/inputValidation/split.ts b/src/utils/inputValidation/split.ts index 43b83154..12064144 100644 --- a/src/utils/inputValidation/split.ts +++ b/src/utils/inputValidation/split.ts @@ -1,8 +1,6 @@ import { ERROR_22, ERROR_32, WARN_17, ERROR_33 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); // include BOM and nbsp const TRIMMABLE_SPACES_REGEX = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/; diff --git a/src/utils/inputValidation/splitExistance.ts b/src/utils/inputValidation/splitExistance.ts index f31f0bf9..b8798f84 100644 --- a/src/utils/inputValidation/splitExistance.ts +++ b/src/utils/inputValidation/splitExistance.ts @@ -2,8 +2,6 @@ import { SPLIT_NOT_FOUND } from '../labels'; import { IReadinessManager } from '../../readiness/types'; import { ILogger } from '../../logger/types'; import { WARN_18 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); /** * This is defined here and in this format mostly because of the logger and the fact that it's considered a validation at product level. diff --git a/src/utils/inputValidation/splits.ts b/src/utils/inputValidation/splits.ts index 71de7998..6807d7da 100644 --- a/src/utils/inputValidation/splits.ts +++ b/src/utils/inputValidation/splits.ts @@ -2,8 +2,6 @@ import { ERROR_34 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { uniq } from '../lang'; import { validateSplit } from './split'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); export function validateSplits(log: ILogger, maybeSplits: any, method: string, listName = 'split_names', item = 'split name'): string[] | false { if (Array.isArray(maybeSplits) && maybeSplits.length > 0) { diff --git a/src/utils/inputValidation/trafficType.ts b/src/utils/inputValidation/trafficType.ts index 53386610..189560e8 100644 --- a/src/utils/inputValidation/trafficType.ts +++ b/src/utils/inputValidation/trafficType.ts @@ -1,8 +1,6 @@ import { ERROR_35, ERROR_36, ERROR_37, WARN_19 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); const CAPITAL_LETTERS_REGEX = /[A-Z]/; diff --git a/src/utils/inputValidation/trafficTypeExistance.ts b/src/utils/inputValidation/trafficTypeExistance.ts index 6b6088da..79244801 100644 --- a/src/utils/inputValidation/trafficTypeExistance.ts +++ b/src/utils/inputValidation/trafficTypeExistance.ts @@ -6,8 +6,6 @@ import { SDKMode } from '../../types'; import { MaybeThenable } from '../../dtos/types'; import { ILogger } from '../../logger/types'; import { WARN_20 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); function logTTExistanceWarning(log: ILogger, maybeTT: string, method: string) { log.warn(WARN_20, [method, maybeTT]); diff --git a/src/utils/settingsValidation/impressionsMode.ts b/src/utils/settingsValidation/impressionsMode.ts index 0b418011..c81f5460 100644 --- a/src/utils/settingsValidation/impressionsMode.ts +++ b/src/utils/settingsValidation/impressionsMode.ts @@ -2,8 +2,6 @@ import { ERROR_38 } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { SplitIO } from '../../types'; import { DEBUG, OPTIMIZED } from '../constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-settings'); export default function validImpressionsMode(log: ILogger, impressionsMode: string): SplitIO.ImpressionsMode { impressionsMode = impressionsMode.toUpperCase(); diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index 7c04ed4f..61ea19c0 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -1,7 +1,5 @@ import { WARN_21 } from '../../../logger/constants'; import { ILogger } from '../../../logger/types'; -// import { logFactory } from '../../../logger/sdkLogger'; -// const log = logFactory('splitio-settings'); /** * This function validates `settings.integrations` object diff --git a/src/utils/settingsValidation/integrations/configurable.ts b/src/utils/settingsValidation/integrations/configurable.ts index dd6d1383..fb24e35b 100644 --- a/src/utils/settingsValidation/integrations/configurable.ts +++ b/src/utils/settingsValidation/integrations/configurable.ts @@ -15,6 +15,6 @@ export function validateConfigurableIntegrations(settings: { log: ILogger, integ return validateIntegrations( settings, integration => integration && isString(integration.type) && validIntegrationTypes.indexOf(integration.type) > -1, - 'Integration items must have a valid \'type\' value' + 'Integration items must have a valid "type" value' ); } diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index 7ff0b872..25e7cf90 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -4,8 +4,6 @@ import { ISplitFiltersValidation } from '../../dtos/types'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; import { WARN_22, WARN_24, WARN_23, DEBUG_51 } from '../../logger/constants'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory(''); // Split filters metadata. // Ordered according to their precedency when forming the filter query string: `&names=&prefixes=` diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index c4ca9aa3..0c5f4171 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -2,8 +2,6 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemorySto import { ISettings } from '../../../types'; import { ILogger } from '../../../logger/types'; import { WARN_25 } from '../../../logger/constants'; -// import { logFactory } from '../../../logger/sdkLogger'; -// const log = logFactory('splitio-settings'); /** * This function validates `settings.storage` object From 940a9c7df59dc2464e3c71dd5002455c9337514c Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 16 Mar 2021 19:02:47 -0300 Subject: [PATCH 35/58] some comment updates --- .../logger/builtinLogger.ts | 27 +++++++------------ .../logger/pluggableLogger.ts | 4 +-- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index b5f108cf..358cb7f0 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -3,7 +3,6 @@ import { ILogger } from '../../../logger/types'; import { LogLevel } from '../../../types'; import { isLocalStorageAvailable } from '../../env/isLocalStorageAvailable'; import { isNode } from '../../env/isNode'; -import { IMap } from '../../lang/maps'; // @TODO when integrating with other packages, find the best way to handle initial state per environment const LS_KEY = 'splitio_debug'; @@ -48,25 +47,19 @@ export function getLogLevel(debugValue: unknown): LogLevel | undefined { } /** - * Factory of logger validator, which validates the `debug` property at config and creates a logger instance with the provided `debug` log level. + * Validates the `debug` property at config and use it to set the log level. + * + * @param settings user config object + * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. */ -export function validateLoggerFactory(msgCodes?: IMap) { +export function validateLogger(settings: { debug: unknown} ): ILogger { - /** - * Validates the `debug` property at config and use it to set the log level. - * - * @param settings user config object - * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. - */ - return function validateLogger(settings: { debug: unknown }): ILogger { + const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; - const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; + const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }); - const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }, msgCodes); + // logs error if the provided settings debug value is invalid + if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); - // logs error if the provided settings debug value is invalid - if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); - - return log; - }; + return log; } diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index 4d36e3a3..2a644618 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -9,13 +9,13 @@ function isLogger(log: any): log is ILogger { * Validates the `debug` (logger) property at config. * * @param settings user config object - * @returns the provided logger at `settings.debug` or a new one with NONE log level if invalid or not provided + * @returns the provided logger at `settings.debug` or a new one with NONE log level if the provided one is invalid */ export function validateLogger(settings: { debug: unknown }): ILogger { const { debug } = settings; const log = new Logger('splitio', { logLevel: 'NONE' }); - // @TODO consider debug of boolean or string types + // @TODO support boolean and string values? if (!debug) return log; if (isLogger(debug)) return debug; From 832c0eb6bc2683f4c0f19507d89226d41bc0b371 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 16 Mar 2021 19:12:38 -0300 Subject: [PATCH 36/58] optimized concat call --- src/logger/browser/debugLogger.ts | 5 ++++- src/logger/browser/errorLogger.ts | 5 ++++- src/logger/browser/infoLogger.ts | 5 ++++- src/logger/browser/warnLogger.ts | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/logger/browser/debugLogger.ts b/src/logger/browser/debugLogger.ts index 84962c0d..f0163454 100644 --- a/src/logger/browser/debugLogger.ts +++ b/src/logger/browser/debugLogger.ts @@ -6,4 +6,7 @@ import { codesDebug } from '../messages/debug'; import { codesDebugBrowser } from '../messages/debugBrowser'; import { _Map } from '../../utils/lang/maps'; -export const debugLogger = new Logger('splitio', { logLevel: 'DEBUG' }, new _Map(codesError.concat(codesWarn).concat(codesInfo).concat(codesDebug).concat(codesDebugBrowser))); +export const debugLogger = new Logger( + 'splitio', { logLevel: 'DEBUG' }, + new _Map(codesError.concat(codesWarn, codesInfo, codesDebug, codesDebugBrowser)) +); diff --git a/src/logger/browser/errorLogger.ts b/src/logger/browser/errorLogger.ts index e9f84c2e..7423d7fc 100644 --- a/src/logger/browser/errorLogger.ts +++ b/src/logger/browser/errorLogger.ts @@ -2,4 +2,7 @@ import { Logger } from '../index'; import { codesError } from '../messages/error'; import { _Map } from '../../utils/lang/maps'; -export const errorLogger = new Logger('splitio', { logLevel: 'ERROR' }, new _Map(codesError)); +export const errorLogger = new Logger( + 'splitio', { logLevel: 'ERROR' }, + new _Map(codesError) +); diff --git a/src/logger/browser/infoLogger.ts b/src/logger/browser/infoLogger.ts index 196d2874..c88c7c8d 100644 --- a/src/logger/browser/infoLogger.ts +++ b/src/logger/browser/infoLogger.ts @@ -4,4 +4,7 @@ import { codesWarn } from '../messages/warn'; import { codesInfo } from '../messages/info'; import { _Map } from '../../utils/lang/maps'; -export const infoLogger = new Logger('splitio', { logLevel: 'INFO' }, new _Map(codesError.concat(codesWarn).concat(codesInfo))); +export const infoLogger = new Logger( + 'splitio', { logLevel: 'INFO' }, + new _Map(codesError.concat(codesWarn, codesInfo)) +); diff --git a/src/logger/browser/warnLogger.ts b/src/logger/browser/warnLogger.ts index 21fce48d..348d4284 100644 --- a/src/logger/browser/warnLogger.ts +++ b/src/logger/browser/warnLogger.ts @@ -3,4 +3,7 @@ import { codesError } from '../messages/error'; import { codesWarn } from '../messages/warn'; import { _Map } from '../../utils/lang/maps'; -export const warnLogger = new Logger('splitio', { logLevel: 'WARN' }, new _Map(codesError.concat(codesWarn))); +export const warnLogger = new Logger( + 'splitio', { logLevel: 'WARN' }, + new _Map(codesError.concat(codesWarn)) +); From bca3fd45f9207ba3e287556dec6ba00dc554ec91 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 17 Mar 2021 16:32:21 -0300 Subject: [PATCH 37/58] polishing and test updates --- src/logger/constants.ts | 46 ++++----- src/logger/messages/error.ts | 36 +++---- src/logger/messages/warn.ts | 18 ++-- .../__tests__/attributes.spec.ts | 4 +- .../inputValidation/__tests__/event.spec.ts | 60 ++++++------ .../__tests__/eventProperties.spec.ts | 35 +++---- .../__tests__/eventValue.spec.ts | 17 ++-- .../inputValidation/__tests__/key.spec.ts | 94 +++++++++---------- .../inputValidation/__tests__/split.spec.ts | 44 ++++----- .../__tests__/splitExistance.spec.ts | 7 +- .../inputValidation/__tests__/splits.spec.ts | 3 +- .../__tests__/trafficType.spec.ts | 42 ++++----- .../__tests__/trafficTypeExistance.spec.ts | 41 ++++---- src/utils/inputValidation/attributes.ts | 4 +- src/utils/inputValidation/event.ts | 10 +- src/utils/inputValidation/eventProperties.ts | 10 +- src/utils/inputValidation/eventValue.ts | 4 +- src/utils/inputValidation/key.ts | 14 +-- src/utils/inputValidation/split.ts | 10 +- src/utils/inputValidation/splitExistance.ts | 4 +- src/utils/inputValidation/splits.ts | 4 +- src/utils/inputValidation/trafficType.ts | 10 +- .../inputValidation/trafficTypeExistance.ts | 4 +- 23 files changed, 238 insertions(+), 283 deletions(-) diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 77ef7339..3e4904be 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -67,29 +67,19 @@ export const ERROR_9 = 309; export const ERROR_10 = 310; export const ERROR_11 = 311; export const ERROR_12 = 312; -export const ERROR_13 = 313; -export const ERROR_14 = 314; -export const ERROR_15 = 315; -export const ERROR_16 = 316; -export const ERROR_17 = 317; -export const ERROR_18 = 318; -export const ERROR_19 = 319; -export const ERROR_20 = 320; +export const ERROR_EVENT_TYPE_FORMAT = 314; +export const ERROR_NOT_PLAIN_OBJECT = 318; +export const ERROR_SIZE_EXCEEDED = 319; +export const ERROR_NOT_FINITE = 320; export const ERROR_21 = 321; -export const ERROR_22 = 322; -export const ERROR_23 = 323; -export const ERROR_24 = 324; -export const ERROR_25 = 325; -export const ERROR_26 = 326; -export const ERROR_32 = 332; -export const ERROR_33 = 333; -export const ERROR_34 = 334; -export const ERROR_35 = 335; -export const ERROR_36 = 336; -export const ERROR_37 = 337; -export const ERROR_38 = 338; +export const ERROR_NULL = 322; +export const ERROR_TOO_LONG = 323; +export const ERROR_INVALID_KEY_OBJECT = 326; +export const ERROR_INVALID = 332; +export const ERROR_EMPTY = 333; +export const ERROR_EMPTY_ARRAY = 334; +export const ERROR_INVALID_ENUM = 338; export const ERROR_39 = 339; -export const ERROR_API_KEY = 340; // node export const ERROR_1 = 301; @@ -132,14 +122,14 @@ export const WARN_8 = 208; export const WARN_9 = 209; export const WARN_10 = 210; export const WARN_11 = 211; -export const WARN_12 = 212; -export const WARN_13 = 213; +export const WARN_SETTING_NULL = 212; +export const WARN_TRIMMING_PROPERTIES = 213; export const WARN_14 = 214; -export const WARN_15 = 215; -export const WARN_17 = 217; -export const WARN_18 = 218; -export const WARN_19 = 219; -export const WARN_20 = 220; +export const WARN_CONVERTING = 215; +export const WARN_TRIMMING = 217; +export const WARN_NOT_EXISTENT_SPLIT = 218; +export const WARN_LOWERCASE_TRAFFIC_TYPE = 219; +export const WARN_NOT_EXISTENT_TT = 220; export const WARN_21 = 221; export const WARN_22 = 222; export const WARN_23 = 223; diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index 9c2cbf1f..eb99b714 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -1,4 +1,4 @@ -import { ERROR_0, ERROR_2, ERROR_3, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_13, ERROR_14, ERROR_15, ERROR_16, ERROR_17, ERROR_18, ERROR_19, ERROR_20, ERROR_21, ERROR_22, ERROR_23, ERROR_24, ERROR_25, ERROR_26, ERROR_32, ERROR_33, ERROR_34, ERROR_35, ERROR_36, ERROR_37, ERROR_38, ERROR_39, ERROR_API_KEY } from '../constants'; +import { ERROR_0, ERROR_2, ERROR_3, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_21, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_ENUM, ERROR_39 } from '../constants'; export const codesError: [number, string][] = [ [ERROR_0, 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'], @@ -11,27 +11,19 @@ export const codesError: [number, string][] = [ [ERROR_10, 'splitio-sync:push-manager => Failed to authenticate for streaming. Error: "%s".'], [ERROR_11, 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'], [ERROR_12, 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'], - [ERROR_13, '%s: attributes must be a plain object.'], - [ERROR_14, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], - [ERROR_15, '%s: you passed a null or undefined event_type, event_type must be a non-empty string.'], - [ERROR_16, '%s: you passed an invalid event_type, event_type must be a non-empty string.'], - [ERROR_17, '%s: you passed an empty event_type, event_type must be a non-empty string.'], - [ERROR_18, '%s: properties must be a plain object.'], - [ERROR_19, '%s: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'], - [ERROR_20, '%s: value must be a finite number.'], [ERROR_21, 'Client has already been destroyed - no calls possible.'], - [ERROR_22, '%s: you passed a null or undefined %s, %s must be a non-empty string.'], - [ERROR_23, '%s: %s too long, %s must be 250 characters or less.'], - [ERROR_24, '%s: you passed an invalid %s type, %s must be a non-empty string.'], - [ERROR_25, '%s: you passed an empty string, %s must be a non-empty string.'], - [ERROR_26, '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'], - [ERROR_32, '%s: you passed an invalid %s, %s must be a non-empty string.'], - [ERROR_33, '%s: you passed an empty %s, %s must be a non-empty string.'], - [ERROR_34, '%s: %s must be a non-empty array.'], - [ERROR_35, '%s: you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.'], - [ERROR_36, '%s: you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.'], - [ERROR_37, '%s: you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.'], - [ERROR_38, 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: "%s" or "%s". Defaulting to "%s" mode.'], [ERROR_39, 'Response status is not OK. Status: %s. URL: %s. Message: %s'], - [ERROR_API_KEY, 'Factory instantiation: %s, api_key must be a non-empty string'] + // input validation + [ERROR_EVENT_TYPE_FORMAT, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], + [ERROR_NOT_PLAIN_OBJECT, '%s: %s must be a plain object.'], + [ERROR_SIZE_EXCEEDED, '%s: the maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'], + [ERROR_NOT_FINITE, '%s: value must be a finite number.'], + [ERROR_NULL, '%s: you passed a null or undefined %s. It must be a non-empty string.'], + [ERROR_TOO_LONG, '%s: %s too long. It must have 250 characters or less.'], + [ERROR_INVALID_KEY_OBJECT, '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'], + [ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'], + [ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'], + [ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'], + // initialization / settings validation + [ERROR_INVALID_ENUM, '%s: you passed an invalid %s. It should be one of the following values: %s. Defaulting to "%s" mode.'], ]; diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index 8e4bca72..9a9e1328 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -1,4 +1,4 @@ -import { WARN_0, WARN_1, WARN_2, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_12, WARN_13, WARN_14, WARN_15, WARN_17, WARN_18, WARN_19, WARN_20, WARN_21, WARN_22, WARN_23, WARN_24, WARN_25, WARN_API_KEY } from '../constants'; +import { WARN_0, WARN_1, WARN_2, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, WARN_14, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_21, WARN_22, WARN_23, WARN_24, WARN_25, WARN_API_KEY } from '../constants'; export const codesWarn: [number, string][] = [ [WARN_0, 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'], @@ -12,14 +12,16 @@ export const codesWarn: [number, string][] = [ [WARN_9, 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'], [WARN_10, 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'], [WARN_11, 'splitio-client:event-tracker => Failed to queue %s'], - [WARN_12, '%s: Property %s is of invalid type. Setting value to null.'], - [WARN_13, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], + // input validation + [WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'], + [WARN_TRIMMING_PROPERTIES, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], [WARN_14, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], - [WARN_15, '%s: %s "%s" is not of type string, converting.'], - [WARN_17, '%s: %s "%s" has extra whitespace, trimming.'], - [WARN_18, '%s: you passed "%s" that does not exist in this environment, please double check what Splits exist in the web console.'], - [WARN_19, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], - [WARN_20, '%s: Traffic Type %s does not have any corresponding Splits in this environment, make sure you\'re tracking your events to a valid traffic type defined in the Split console.'], + [WARN_CONVERTING, '%s: %s "%s" is not of type string, converting.'], + [WARN_TRIMMING, '%s: %s "%s" has extra whitespace, trimming.'], + [WARN_NOT_EXISTENT_SPLIT, '%s: split "%s" does not exist in this environment, please double check what splits exist in the web console.'], + [WARN_LOWERCASE_TRAFFIC_TYPE, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], + [WARN_NOT_EXISTENT_TT, '%s: traffic type "%s" does not have any corresponding split in this environment, make sure you\'re tracking your events to a valid traffic type defined in the web console.'], + // initialization / settings validation [WARN_21, 'splitio-settings => %s integration %s at settings %s invalid. %s'], [WARN_22, 'Factory instantiation: split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'], [WARN_23, 'Factory instantiation: split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'], diff --git a/src/utils/inputValidation/__tests__/attributes.spec.ts b/src/utils/inputValidation/__tests__/attributes.spec.ts index e7ae5e0d..ae7b2c9b 100644 --- a/src/utils/inputValidation/__tests__/attributes.spec.ts +++ b/src/utils/inputValidation/__tests__/attributes.spec.ts @@ -1,4 +1,4 @@ -import { ERROR_13 } from '../../../logger/constants'; +import { ERROR_NOT_PLAIN_OBJECT } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateAttributes } from '../attributes'; @@ -41,7 +41,7 @@ describe('INPUT VALIDATION for Attributes', () => { const invalidAttribute = invalidAttributes[i]; expect(validateAttributes(loggerMock, invalidAttribute, 'test_method')).toBe(false); // Invalid attribute objects should return false. - expect(loggerMock.error).lastCalledWith(ERROR_13, ['test_method']); // The error should be logged for the invalid attributes map. + expect(loggerMock.error).lastCalledWith(ERROR_NOT_PLAIN_OBJECT, ['test_method', 'attributes']); // The error should be logged for the invalid attributes map. loggerMock.error.mockClear(); } diff --git a/src/utils/inputValidation/__tests__/event.spec.ts b/src/utils/inputValidation/__tests__/event.spec.ts index 9abfdff1..2e54136b 100644 --- a/src/utils/inputValidation/__tests__/event.spec.ts +++ b/src/utils/inputValidation/__tests__/event.spec.ts @@ -1,34 +1,28 @@ +import { ERROR_INVALID, ERROR_EMPTY, ERROR_NULL, ERROR_EVENT_TYPE_FORMAT } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateEvent } from '../event'; -const errorMsgs = { - NULL_EVENT: () => 'you passed a null or undefined event_type, event_type must be a non-empty string.', - WRONG_TYPE_EVENT: () => 'you passed an invalid event_type, event_type must be a non-empty string.', - EMPTY_EVENT: () => 'you passed an empty event_type, event_type must be a non-empty string.', - WRONG_FORMAT_EVENT: (invalidEvent: any) => `you passed "${invalidEvent}", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.` -}; - const invalidEvents = [ - { event: [], msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: () => { }, msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: false, msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: true, msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: {}, msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: Object.create({}), msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: 'something+withInvalidchars', msg: errorMsgs.WRONG_FORMAT_EVENT }, - { event: 'with spaces', msg: errorMsgs.WRONG_FORMAT_EVENT }, - { event: ' asd', msg: errorMsgs.WRONG_FORMAT_EVENT }, - { event: 'asd ', msg: errorMsgs.WRONG_FORMAT_EVENT }, - { event: '?', msg: errorMsgs.WRONG_FORMAT_EVENT }, - { event: '', msg: errorMsgs.EMPTY_EVENT }, - { event: NaN, msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: -Infinity, msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: Infinity, msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: new Promise(res => res), msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: Symbol('asd'), msg: errorMsgs.WRONG_TYPE_EVENT }, - { event: null, msg: errorMsgs.NULL_EVENT }, - { event: undefined, msg: errorMsgs.NULL_EVENT } + { event: [], msg: ERROR_INVALID }, + { event: () => { }, msg: ERROR_INVALID }, + { event: false, msg: ERROR_INVALID }, + { event: true, msg: ERROR_INVALID }, + { event: {}, msg: ERROR_INVALID }, + { event: Object.create({}), msg: ERROR_INVALID }, + { event: 'something+withInvalidchars', msg: ERROR_EVENT_TYPE_FORMAT }, + { event: 'with spaces', msg: ERROR_EVENT_TYPE_FORMAT }, + { event: ' asd', msg: ERROR_EVENT_TYPE_FORMAT }, + { event: 'asd ', msg: ERROR_EVENT_TYPE_FORMAT }, + { event: '?', msg: ERROR_EVENT_TYPE_FORMAT }, + { event: '', msg: ERROR_EMPTY }, + { event: NaN, msg: ERROR_INVALID }, + { event: -Infinity, msg: ERROR_INVALID }, + { event: Infinity, msg: ERROR_INVALID }, + { event: new Promise(res => res), msg: ERROR_INVALID }, + { event: Symbol('asd'), msg: ERROR_INVALID }, + { event: null, msg: ERROR_NULL }, + { event: undefined, msg: ERROR_NULL } ]; describe('INPUT VALIDATION for Event types', () => { @@ -38,26 +32,26 @@ describe('INPUT VALIDATION for Event types', () => { test('Should return the provided event type if it is a valid string without logging any errors', () => { expect(validateEvent(loggerMock, 'valid:Too', 'some_method_eventType')).toBe('valid:Too'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. expect(validateEvent(loggerMock, 'I.am.valid-string_ValUe', 'some_method_eventType')).toBe('I.am.valid-string_ValUe'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. expect(validateEvent(loggerMock, 'a', 'some_method_eventType')).toBe('a'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should return false and log error if event type is not a valid string', () => { for (let i = 0; i < invalidEvents.length; i++) { const invalidValue = invalidEvents[i]['event']; - const expectedLog = invalidEvents[i]['msg'](invalidValue); + const expectedLog = invalidEvents[i]['msg']; expect(validateEvent(loggerMock, invalidValue, 'test_method')).toBe(false); // Invalid event types should always return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. + expect(loggerMock.error).toBeCalledWith(expectedLog, expectedLog === ERROR_EVENT_TYPE_FORMAT ? ['test_method', invalidValue] : ['test_method']); // Should log the error for the invalid event type. loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); }); diff --git a/src/utils/inputValidation/__tests__/eventProperties.spec.ts b/src/utils/inputValidation/__tests__/eventProperties.spec.ts index 3f2caa9b..d17f08bd 100644 --- a/src/utils/inputValidation/__tests__/eventProperties.spec.ts +++ b/src/utils/inputValidation/__tests__/eventProperties.spec.ts @@ -1,3 +1,4 @@ +import { ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateEventProperties } from '../eventProperties'; @@ -48,8 +49,8 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return the passed null since it is valid with default event size.'); - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('When setting a value for properties, only objects are acceptable', () => { @@ -59,12 +60,12 @@ describe('INPUT VALIDATION for Event Properties', () => { properties: false, size: 1024 }); // It should return default size and properties false if the properties value is not an object or null/undefined.'); - expect(loggerMock.error.mock.calls).toEqual([['some_method_eventProps: properties must be a plain object.']]); // Should log an error. + expect(loggerMock.error).toBeCalledWith(ERROR_NOT_PLAIN_OBJECT, ['some_method_eventProps', 'properties']); // Should log an error. loggerMock.error.mockClear(); }); - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('It should return the properties object when valid and also the correct event size', () => { @@ -87,8 +88,8 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(validProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('It should return the properties object when valid and also the correct event size, nulling any invalid prop', () => { @@ -117,11 +118,11 @@ describe('INPUT VALIDATION for Event Properties', () => { expect(providedProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(4); // It should have logged one warning per each property of the invalid type. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).toBeCalledTimes(4); // It should have logged one warning per each property of the invalid type. ['willBeNulled1', 'willBeNulled2', 'willBeNulled3', 'willBeNulled4'].forEach((key, index) => { - expect(loggerMock.warn.mock.calls[index][0]).toBe(`some_method_eventProps: Property ${key} is of invalid type. Setting value to null.`); + expect(loggerMock.warn.mock.calls[index]).toEqual([WARN_SETTING_NULL, ['some_method_eventProps', key]]); }); }); @@ -139,8 +140,8 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return the properties and the event size.'); - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. // @ts-ignore validProperties.a = null; // Adding one prop to exceed the limit. @@ -152,8 +153,8 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return the properties and the event size.'); - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls).toEqual([['some_method_eventProps: Event has more than 300 properties. Some of them will be trimmed when processed.']]); // It should have logged a warning. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).toBeCalledWith(WARN_TRIMMING_PROPERTIES, ['some_method_eventProps']); // It should have logged a warning. }); const fiveHundredChars = 'JKHSAKFJASHFJKASHSFKHAKJSGJKASGH1234567890JASHGJHASGJKAHSJKGHAJKSHGJKAHGJKASHajksghkjahsgjkhsakjghjkashgjkhagjkhajksghjkahsgjksahgjkahsgjkhasgjkhsagjkabsgjhaenjkrnjkwnqrkjnqwekjrnkjweqntkjnjkenasdjkngjksdajkghkjdasgkjnadsjgn asdkjgnkjsadngkjnasdjkngjknasdkjgnasdlgnsdakgnlkasndugbuoewqoitnwlkgadsgjdnsagubadisugboisdngklasdgndsgbjasdbgjkasbdgubuiqwetoiqhweiojtioweqhtiohqweiohtiowqehtoihewqiobtgoiqwengiowqnegionwqeogiqwneoignqiowegnioqewgnwqoiegnoiqwengiowqnegoinqwgionqwegionwqeoignqwegoinoiadnfaosignoiansgk'; @@ -174,8 +175,8 @@ describe('INPUT VALIDATION for Event Properties', () => { // It should return the properties and the event size.'); expect(validProperties).not.toBe(output.properties); // Returned properties should be a clone. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).not.toBeCalled(); // Should not log any warnings. // @ts-ignore validProperties.a = null; // exceed by two bytes (1 char string key which is two bytes, null value which we count as 0 to match other SDKs) @@ -188,7 +189,7 @@ describe('INPUT VALIDATION for Event Properties', () => { }); // It should return false instead of the properties and the event size.'); - expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. - expect(loggerMock.error.mock.calls).toEqual([['some_method_eventProps: The maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.']]); // Should log an error. + expect(loggerMock.warn).not.toBeCalled(); // Should not log any warnings. + expect(loggerMock.error).toBeCalledWith(ERROR_SIZE_EXCEEDED, ['some_method_eventProps']); // Should log an error. }); }); diff --git a/src/utils/inputValidation/__tests__/eventValue.spec.ts b/src/utils/inputValidation/__tests__/eventValue.spec.ts index b98ca3c0..dc7d0f33 100644 --- a/src/utils/inputValidation/__tests__/eventValue.spec.ts +++ b/src/utils/inputValidation/__tests__/eventValue.spec.ts @@ -1,3 +1,4 @@ +import { ERROR_NOT_FINITE } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateEventValue } from '../eventValue'; @@ -23,20 +24,20 @@ describe('INPUT VALIDATION for Event Values', () => { test('Should return the passed value if it is a valid finite number without logging any errors', () => { expect(validateEventValue(loggerMock, 50, 'some_method_eventValue')).toBe(50); // It should return the passed number if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. expect(validateEventValue(loggerMock, -50, 'some_method_eventValue')).toBe(-50); // It should return the passed number if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should return the passed value if it is a null or undefined (since it is optional) without logging any errors', () => { expect(validateEventValue(loggerMock, null, 'some_method_eventValue')).toBe(null); // It should return the passed number if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. expect(validateEventValue(loggerMock, undefined, 'some_method_eventValue')).toBe(undefined); // It should return the passed number if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should return false and log error if event value is not a valid finite number', () => { @@ -44,11 +45,11 @@ describe('INPUT VALIDATION for Event Values', () => { const invalidValue = invalidValues[i]; expect(validateEventValue(loggerMock, invalidValue, 'test_method')).toBe(false); // Invalid event values should always return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual('test_method: value must be a finite number.'); // Should log the error for the invalid event value. + expect(loggerMock.error).toBeCalledWith(ERROR_NOT_FINITE, ['test_method']); // Should log the error for the invalid event value. loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); }); diff --git a/src/utils/inputValidation/__tests__/key.spec.ts b/src/utils/inputValidation/__tests__/key.spec.ts index 62600870..74bdb62e 100644 --- a/src/utils/inputValidation/__tests__/key.spec.ts +++ b/src/utils/inputValidation/__tests__/key.spec.ts @@ -1,35 +1,27 @@ +import { ERROR_EMPTY, ERROR_INVALID, ERROR_INVALID_KEY_OBJECT, ERROR_NULL, ERROR_TOO_LONG, WARN_CONVERTING } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateKey } from '../key'; -const errorMsgs = { - EMPTY_KEY: (keyType: string) => `you passed an empty string, ${keyType} must be a non-empty string.`, - LONG_KEY: (keyType: string) => `${keyType} too long, ${keyType} must be 250 characters or less.`, - NULL_KEY: (keyType: string) => `you passed a null or undefined ${keyType}, ${keyType} must be a non-empty string.`, - WRONG_TYPE_KEY: (keyType: string) => `you passed an invalid ${keyType} type, ${keyType} must be a non-empty string.`, - NUMERIC_KEY: (keyType: string, value: any) => `${keyType} "${value}" is not of type string, converting.`, - WRONG_KEY_PROPS: 'Key must be an object with bucketingKey and matchingKey with valid string properties.' -}; - const invalidKeys = [ - { key: '', msg: errorMsgs.EMPTY_KEY }, - { key: 'a'.repeat(251), msg: errorMsgs.LONG_KEY }, - { key: null, msg: errorMsgs.NULL_KEY }, - { key: undefined, msg: errorMsgs.NULL_KEY }, - { key: () => { }, msg: errorMsgs.WRONG_TYPE_KEY }, - { key: new Promise(r => r()), msg: errorMsgs.WRONG_TYPE_KEY }, - { key: Symbol('asd'), msg: errorMsgs.WRONG_TYPE_KEY }, - { key: [], msg: errorMsgs.WRONG_TYPE_KEY }, - { key: true, msg: errorMsgs.WRONG_TYPE_KEY }, - { key: NaN, msg: errorMsgs.WRONG_TYPE_KEY }, - { key: Infinity, msg: errorMsgs.WRONG_TYPE_KEY }, - { key: -Infinity, msg: errorMsgs.WRONG_TYPE_KEY }, + { key: '', msg: ERROR_EMPTY }, + { key: 'a'.repeat(251), msg: ERROR_TOO_LONG }, + { key: null, msg: ERROR_NULL }, + { key: undefined, msg: ERROR_NULL }, + { key: () => { }, msg: ERROR_INVALID }, + { key: new Promise(r => r()), msg: ERROR_INVALID }, + { key: Symbol('asd'), msg: ERROR_INVALID }, + { key: [], msg: ERROR_INVALID }, + { key: true, msg: ERROR_INVALID }, + { key: NaN, msg: ERROR_INVALID }, + { key: Infinity, msg: ERROR_INVALID }, + { key: -Infinity, msg: ERROR_INVALID }, ]; const stringifyableKeys = [ - { key: 200, msg: errorMsgs.NUMERIC_KEY }, - { key: 1235891238571295, msg: errorMsgs.NUMERIC_KEY }, - { key: 0, msg: errorMsgs.NUMERIC_KEY } + { key: 200, msg: WARN_CONVERTING }, + { key: 1235891238571295, msg: WARN_CONVERTING }, + { key: 0, msg: WARN_CONVERTING } ]; const invalidKeyObjects = [ @@ -51,52 +43,52 @@ describe('INPUT VALIDATION for Key', () => { }; expect(validateKey(loggerMock, validKey, 'some_method_keys')).toEqual(validKey); // It will return the valid key. - expect(loggerMock.error.mock.calls.length).toBe(0); // No errors should be logged. + expect(loggerMock.error).not.toBeCalled(); // No errors should be logged. expect(validateKey(loggerMock, validObjKey, 'some_method_keys')).toEqual(validObjKey); // It will return the valid key. - expect(loggerMock.error.mock.calls.length).toBe(0); // No errors should be logged. + expect(loggerMock.error).not.toBeCalled(); // No errors should be logged. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('String key / Should return false and log error if key is invalid', () => { for (let i = 0; i < invalidKeys.length; i++) { const invalidKey = invalidKeys[i]['key']; - const expectedLog = invalidKeys[i]['msg']('key'); + const expectedLog = invalidKeys[i]['msg']; expect(validateKey(loggerMock, invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(loggerMock.error).toBeCalledWith(expectedLog, ['test_method', 'key']); // The error should be logged for the invalid key. loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('String key / Should return stringified version of the key if it is convertible to one and log a warning.', () => { for (let i = 0; i < stringifyableKeys.length; i++) { const invalidKey = stringifyableKeys[i]['key']; - const expectedLog = stringifyableKeys[i]['msg']('key', invalidKey); + const expectedLog = stringifyableKeys[i]['msg']; validateKey(loggerMock, invalidKey, 'test_method'); - expect(loggerMock.warn.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // But if the logger allows for warnings, it should be logged. + expect(loggerMock.warn).toBeCalledWith(expectedLog, ['test_method', 'key', invalidKey]); // But if the logger allows for warnings, it should be logged. loggerMock.warn.mockClear(); } - expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.error).not.toBeCalled(); // It should have not logged any errors. }); test('Object key / Should return false and log error if a part of the key is invalid', () => { // Test invalid object format for (let i = 0; i < invalidKeyObjects.length; i++) { expect(validateKey(loggerMock, invalidKeyObjects[i], 'test_method')).toBe(false); // Invalid key objects should return false. - expect(loggerMock.error.mock.calls[loggerMock.error.mock.calls.length - 1][0]).toEqual(`test_method: ${errorMsgs.WRONG_KEY_PROPS}`); // The error should be logged for the invalid key. + expect(loggerMock.error).lastCalledWith(ERROR_INVALID_KEY_OBJECT, ['test_method']); // The error should be logged for the invalid key. loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. loggerMock.mockClear(); // Test invalid matchingKey @@ -105,15 +97,15 @@ describe('INPUT VALIDATION for Key', () => { matchingKey: invalidKeys[i]['key'], bucketingKey: 'thisIsValid' }; - const expectedLog = invalidKeys[i]['msg']('matchingKey'); + const expectedLog = invalidKeys[i]['msg']; expect(validateKey(loggerMock, invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(loggerMock.error).toBeCalledWith(expectedLog, ['test_method', 'matchingKey']); // The error should be logged for the invalid key. loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. loggerMock.mockClear(); @@ -123,15 +115,15 @@ describe('INPUT VALIDATION for Key', () => { matchingKey: 'thisIsValidToo', bucketingKey: invalidKeys[i]['key'] }; - const expectedLog = invalidKeys[i]['msg']('bucketingKey'); + const expectedLog = invalidKeys[i]['msg']; expect(validateKey(loggerMock, invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // The error should be logged for the invalid key. + expect(loggerMock.error).toBeCalledWith(expectedLog, ['test_method', 'bucketingKey']); // The error should be logged for the invalid key. loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. loggerMock.mockClear(); @@ -140,14 +132,14 @@ describe('INPUT VALIDATION for Key', () => { matchingKey: invalidKeys[0]['key'], bucketingKey: invalidKeys[1]['key'] }; - let expectedLogMK = invalidKeys[0]['msg']('matchingKey'); - let expectedLogBK = invalidKeys[1]['msg']('bucketingKey'); + let expectedLogMK = invalidKeys[0]['msg']; + let expectedLogBK = invalidKeys[1]['msg']; expect(validateKey(loggerMock, invalidKey, 'test_method')).toBe(false); // Invalid keys should return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The error should be logged for the invalid key property. - expect(loggerMock.error.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The error should be logged for the invalid key property. + expect(loggerMock.error).nthCalledWith(1, expectedLogMK, ['test_method', 'matchingKey']); // The error should be logged for the invalid key property. + expect(loggerMock.error).nthCalledWith(2, expectedLogBK, ['test_method', 'bucketingKey']); // The error should be logged for the invalid key property. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Object key / Should return stringified version of the key props if those are convertible and log the corresponding warnings', () => { @@ -159,13 +151,13 @@ describe('INPUT VALIDATION for Key', () => { matchingKey: String(invalidKey.matchingKey), bucketingKey: String(invalidKey.bucketingKey), }; - let expectedLogMK = stringifyableKeys[0]['msg']('matchingKey', invalidKey.matchingKey); - let expectedLogBK = stringifyableKeys[1]['msg']('bucketingKey', invalidKey.bucketingKey); + let expectedLogMK = stringifyableKeys[0]['msg']; + let expectedLogBK = stringifyableKeys[1]['msg']; expect(validateKey(loggerMock, invalidKey, 'test_method')).toEqual(expectedKey); // If a key object had stringifyable values, those will be stringified and Key returned. - expect(loggerMock.warn.mock.calls[0][0]).toEqual(`test_method: ${expectedLogMK}`); // The warning should be logged for the stringified prop if warnings are enabled. - expect(loggerMock.warn.mock.calls[1][0]).toEqual(`test_method: ${expectedLogBK}`); // The warning should be logged for the stringified prop if warnings are enabled. + expect(loggerMock.warn).nthCalledWith(1, expectedLogMK, ['test_method', 'matchingKey', invalidKey.matchingKey]); // The warning should be logged for the stringified prop if warnings are enabled. + expect(loggerMock.warn).nthCalledWith(2, expectedLogBK, ['test_method', 'bucketingKey', invalidKey.bucketingKey]); // The warning should be logged for the stringified prop if warnings are enabled. - expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.error).not.toBeCalled(); // It should have not logged any errors. }); }); diff --git a/src/utils/inputValidation/__tests__/split.spec.ts b/src/utils/inputValidation/__tests__/split.spec.ts index 1a6417b9..13ccfaa3 100644 --- a/src/utils/inputValidation/__tests__/split.spec.ts +++ b/src/utils/inputValidation/__tests__/split.spec.ts @@ -1,30 +1,24 @@ +import { ERROR_INVALID, ERROR_NULL, ERROR_EMPTY, WARN_TRIMMING } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateSplit } from '../split'; -const errorMsgs = { - NULL_SPLIT: () => 'you passed a null or undefined split name, split name must be a non-empty string.', - WRONG_TYPE_SPLIT: () => 'you passed an invalid split name, split name must be a non-empty string.', - EMPTY_SPLIT: () => 'you passed an empty split name, split name must be a non-empty string.', - TRIMMABLE_SPLIT: (splitName: string) => `split name "${splitName}" has extra whitespace, trimming.` -}; - const invalidSplits = [ - { split: [], msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: () => { }, msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: Object.create({}), msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: {}, msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: true, msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: false, msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: 10, msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: 0, msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: NaN, msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: Infinity, msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: null, msg: errorMsgs.NULL_SPLIT }, - { split: undefined, msg: errorMsgs.NULL_SPLIT }, - { split: new Promise(res => res), msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: Symbol('asd'), msg: errorMsgs.WRONG_TYPE_SPLIT }, - { split: '', msg: errorMsgs.EMPTY_SPLIT } + { split: [], msg: ERROR_INVALID }, + { split: () => { }, msg: ERROR_INVALID }, + { split: Object.create({}), msg: ERROR_INVALID }, + { split: {}, msg: ERROR_INVALID }, + { split: true, msg: ERROR_INVALID }, + { split: false, msg: ERROR_INVALID }, + { split: 10, msg: ERROR_INVALID }, + { split: 0, msg: ERROR_INVALID }, + { split: NaN, msg: ERROR_INVALID }, + { split: Infinity, msg: ERROR_INVALID }, + { split: null, msg: ERROR_NULL }, + { split: undefined, msg: ERROR_NULL }, + { split: new Promise(res => res), msg: ERROR_INVALID }, + { split: Symbol('asd'), msg: ERROR_INVALID }, + { split: '', msg: ERROR_EMPTY } ]; const trimmableSplits = [ @@ -52,7 +46,7 @@ describe('INPUT VALIDATION for Split name', () => { for (let i = 0; i < trimmableSplits.length; i++) { const trimmableSplit = trimmableSplits[i]; expect(validateSplit(loggerMock, trimmableSplit, 'some_method_splitName')).toBe(trimmableSplit.trim()); // It should return the trimmed version of the split name received. - expect(loggerMock.warn.mock.calls[0][0]).toEqual(`some_method_splitName: ${errorMsgs.TRIMMABLE_SPLIT(trimmableSplit)}`); // Should log a warning if those are enabled. + expect(loggerMock.warn).toBeCalledWith(WARN_TRIMMING, ['some_method_splitName', 'split name', trimmableSplit]); // Should log a warning if those are enabled. loggerMock.warn.mockClear(); } @@ -64,10 +58,10 @@ describe('INPUT VALIDATION for Split name', () => { for (let i = 0; i < invalidSplits.length; i++) { const invalidValue = invalidSplits[i]['split']; // @ts-ignore - const expectedLog = invalidSplits[i]['msg'](invalidValue); + const expectedLog = invalidSplits[i]['msg']; expect(validateSplit(loggerMock, invalidValue, 'test_method')).toBe(false); // Invalid event types should always return false. - expect(loggerMock.error.mock.calls[0][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid event type. + expect(loggerMock.error).toBeCalledWith(expectedLog, ['test_method', 'split name']); // Should log the error for the invalid event type. loggerMock.error.mockClear(); } diff --git a/src/utils/inputValidation/__tests__/splitExistance.spec.ts b/src/utils/inputValidation/__tests__/splitExistance.spec.ts index ae1cfd5f..6b72ad87 100644 --- a/src/utils/inputValidation/__tests__/splitExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/splitExistance.spec.ts @@ -5,10 +5,7 @@ import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateSplitExistance } from '../splitExistance'; import { IReadinessManager } from '../../../readiness/types'; - -const errorMsgs = { - NOT_EXISTENT_SPLIT: (splitName: string) => `you passed "${splitName}" that does not exist in this environment, please double check what Splits exist in the web console.` -}; +import { WARN_NOT_EXISTENT_SPLIT } from '../../../logger/constants'; describe('Split existance (special case)', () => { @@ -43,7 +40,7 @@ describe('Split existance (special case)', () => { expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', LabelConstants.SPLIT_NOT_FOUND, 'other_method')).toBe(false); // Should return false if it receives a label but it is the split not found one. expect(loggerMock.warn.mock.calls.length).toBe(3); // It should have logged 3 warnings, one per each time we called it - loggerMock.warn.mock.calls.forEach(call => expect(call[0]).toBe(`other_method: ${errorMsgs.NOT_EXISTENT_SPLIT('other_split')}`)); // Warning logs should have the correct message. + loggerMock.warn.mock.calls.forEach(call => expect(call).toEqual([WARN_NOT_EXISTENT_SPLIT, ['other_method', 'other_split']])); // Warning logs should have the correct message. expect(loggerMock.error.mock.calls.length).toBe(0); // We log warnings, not errors. }); diff --git a/src/utils/inputValidation/__tests__/splits.spec.ts b/src/utils/inputValidation/__tests__/splits.spec.ts index 1bbe14d0..a4d51b71 100644 --- a/src/utils/inputValidation/__tests__/splits.spec.ts +++ b/src/utils/inputValidation/__tests__/splits.spec.ts @@ -3,6 +3,7 @@ import startsWith from 'lodash/startsWith'; // mocks sdkLogger import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; +import { ERROR_EMPTY_ARRAY } from '../../../logger/constants'; // mocks validateSplit jest.mock('../split'); @@ -61,7 +62,7 @@ describe('INPUT VALIDATION for Split names', () => { test('Should return false and log an error for the array if it is invalid', () => { for (let i = 0; i < invalidSplits.length; i++) { expect(validateSplits(loggerMock, invalidSplits[i], 'test_method')).toBe(false); // It will return false as the array is of an incorrect type. - expect(loggerMock.error.mock.calls).toEqual([['test_method: split_names must be a non-empty array.']]); // Should log the error for the collection. + expect(loggerMock.error).toBeCalledWith(ERROR_EMPTY_ARRAY, ['test_method', 'split_names']); // Should log the error for the collection. expect(validateSplitMock.mock.calls.length).toBe(0); // Should not try to validate any inner value if there is no valid array. loggerMock.error.mockClear(); diff --git a/src/utils/inputValidation/__tests__/trafficType.spec.ts b/src/utils/inputValidation/__tests__/trafficType.spec.ts index 2b5af848..43355676 100644 --- a/src/utils/inputValidation/__tests__/trafficType.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficType.spec.ts @@ -1,30 +1,24 @@ +import { ERROR_NULL, ERROR_INVALID, ERROR_EMPTY, WARN_LOWERCASE_TRAFFIC_TYPE } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateTrafficType } from '../trafficType'; -const errorMsgs = { - NULL_TRAFFIC_TYPE: 'you passed a null or undefined traffic_type_name, traffic_type_name must be a non-empty string.', - WRONG_TYPE_TRAFFIC_TYPE: 'you passed an invalid traffic_type_name, traffic_type_name must be a non-empty string.', - EMPTY_TRAFFIC_TYPE: 'you passed an empty traffic_type_name, traffic_type_name must be a non-empty string.', - LOWERCASE_TRAFFIC_TYPE: 'traffic_type_name should be all lowercase - converting string to lowercase.' -}; - const invalidTrafficTypes = [ - { tt: [], msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: () => { }, msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: Object.create({}), msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: {}, msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: true, msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: false, msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: 10, msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: 0, msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: NaN, msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: Infinity, msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: null, msg: errorMsgs.NULL_TRAFFIC_TYPE }, - { tt: undefined, msg: errorMsgs.NULL_TRAFFIC_TYPE }, - { tt: new Promise(res => res), msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: Symbol('asd'), msg: errorMsgs.WRONG_TYPE_TRAFFIC_TYPE }, - { tt: '', msg: errorMsgs.EMPTY_TRAFFIC_TYPE } + { tt: [], msg: ERROR_INVALID }, + { tt: () => { }, msg: ERROR_INVALID }, + { tt: Object.create({}), msg: ERROR_INVALID }, + { tt: {}, msg: ERROR_INVALID }, + { tt: true, msg: ERROR_INVALID }, + { tt: false, msg: ERROR_INVALID }, + { tt: 10, msg: ERROR_INVALID }, + { tt: 0, msg: ERROR_INVALID }, + { tt: NaN, msg: ERROR_INVALID }, + { tt: Infinity, msg: ERROR_INVALID }, + { tt: null, msg: ERROR_NULL }, + { tt: undefined, msg: ERROR_NULL }, + { tt: new Promise(res => res), msg: ERROR_INVALID }, + { tt: Symbol('asd'), msg: ERROR_INVALID }, + { tt: '', msg: ERROR_EMPTY } ]; const convertibleTrafficTypes = [ @@ -53,7 +47,7 @@ describe('INPUT VALIDATION for Traffic Types', () => { const convertibleTrafficType = convertibleTrafficTypes[i]; expect(validateTrafficType(loggerMock, convertibleTrafficType, 'some_method_trafficType')).toBe(convertibleTrafficType.toLowerCase()); // It should return the lowercase version of the traffic type received. - expect(loggerMock.warn.mock.calls[i][0]).toEqual(`some_method_trafficType: ${errorMsgs.LOWERCASE_TRAFFIC_TYPE}`); // Should log a warning. + expect(loggerMock.warn.mock.calls[i]).toEqual([WARN_LOWERCASE_TRAFFIC_TYPE, ['some_method_trafficType']]); // Should log a warning. } expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. @@ -65,7 +59,7 @@ describe('INPUT VALIDATION for Traffic Types', () => { const expectedLog = invalidTrafficTypes[i]['msg']; expect(validateTrafficType(loggerMock, invalidValue, 'test_method')).toBe(false); // Invalid traffic types should always return false. - expect(loggerMock.error.mock.calls[i][0]).toEqual(`test_method: ${expectedLog}`); // Should log the error for the invalid traffic type. + expect(loggerMock.error.mock.calls[i]).toEqual([expectedLog, ['test_method']]); // Should log the error for the invalid traffic type. } expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. diff --git a/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts b/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts index f8e30bd7..ba2f1666 100644 --- a/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficTypeExistance.spec.ts @@ -2,6 +2,7 @@ import { IReadinessManager } from '../../../readiness/types'; import { ISplitsCacheBase } from '../../../storages/types'; import { LOCALHOST_MODE, STANDALONE_MODE } from '../../constants'; import thenable from '../../promise/thenable'; +import { WARN_NOT_EXISTENT_TT } from '../../../logger/constants'; /** Mocks */ import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; @@ -29,10 +30,6 @@ const splitsCacheMock = { /** Test target */ import { validateTrafficTypeExistance } from '../trafficTypeExistance'; -const errorMsgs = { - NOT_EXISTENT_TT: (ttName: string) => `Traffic Type ${ttName} does not have any corresponding Splits in this environment, make sure you're tracking your events to a valid traffic type defined in the Split console.` -}; - describe('validateTrafficTypeExistance', () => { afterEach(() => { @@ -43,16 +40,16 @@ describe('validateTrafficTypeExistance', () => { test('Should return true without going to the storage and log nothing if the SDK is not ready or in localhost mode', () => { // Not ready and not localstorage expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is not ready yet, it will return true. - expect(splitsCacheMock.trafficTypeExists.mock.calls.length).toBe(0); // If the SDK is not ready yet, it does not try to go to the storage. - expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. - expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is not ready yet, it will not log any errors. + expect(splitsCacheMock.trafficTypeExists).not.toBeCalled(); // If the SDK is not ready yet, it does not try to go to the storage. + expect(loggerMock.error).not.toBeCalled(); // If the SDK is not ready yet, it will not log any errors. + expect(loggerMock.error).not.toBeCalled(); // If the SDK is not ready yet, it will not log any errors. // Ready and in localstorage mode. readinessManagerMock.isReady.mockImplementation(() => true); expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, LOCALHOST_MODE, 'test_tt', 'test_method')).toBe(true); // If the SDK is in localhost mode, it will return true. - expect(splitsCacheMock.trafficTypeExists.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it does not try to go to the storage. - expect(loggerMock.warn.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is in localhost mode, it will not log any errors. + expect(splitsCacheMock.trafficTypeExists).not.toBeCalled(); // If the SDK is in localhost mode, it does not try to go to the storage. + expect(loggerMock.warn).not.toBeCalled(); // If the SDK is in localhost mode, it will not log any warnings. + expect(loggerMock.error).not.toBeCalled(); // If the SDK is in localhost mode, it will not log any errors. }); test('Should return true and log nothing if SDK Ready, not localhost mode and the traffic type exists in the storage', () => { @@ -61,16 +58,16 @@ describe('validateTrafficTypeExistance', () => { expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_EXISTENT_TT, 'test_method')).toBe(true); // If the SDK is in condition to validate but the TT exists, it will return true. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_EXISTENT_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the storage. - expect(loggerMock.warn.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // If the SDK is in condition to validate but the TT exists, it will not log any errors. + expect(loggerMock.warn).not.toBeCalled(); // If the SDK is in condition to validate but the TT exists, it will not log any warnings. + expect(loggerMock.error).not.toBeCalled(); // If the SDK is in condition to validate but the TT exists, it will not log any errors. }); test('Should return false and log warning if SDK Ready, not localhost mode and the traffic type does NOT exist in the storage', () => { // Ready, standalone, and the TT not exists in the storage. expect(validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_NOT_EXISTENT_TT, 'test_method_y')).toBe(false); // If the SDK is in condition to validate but the TT does not exist in the storage, it will return false. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_NOT_EXISTENT_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the storage. - expect(loggerMock.warn.mock.calls).toEqual([[`test_method_y: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. - expect(loggerMock.error.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. + expect(loggerMock.warn).toBeCalledWith(WARN_NOT_EXISTENT_TT, ['test_method_y', TEST_NOT_EXISTENT_TT]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. + expect(loggerMock.error).not.toBeCalled(); // It logged a warning so no errors should be logged. }); test('validateTrafficTypeExistance w/async storage - If the storage is async but the SDK is in condition to validate, it will validate that the TT exists on the storage', async () => { @@ -79,14 +76,14 @@ describe('validateTrafficTypeExistance', () => { const validationPromise = validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_EXISTENT_ASYNC_TT, 'test_method_z'); expect(thenable(validationPromise)).toBe(true); // If the storage is async, it should also return a promise. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_EXISTENT_ASYNC_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the async storage. - expect(loggerMock.warn.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. - expect(loggerMock.error.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.warn).not.toBeCalled(); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.error).not.toBeCalled(); // We are still fetching the data from the storage, no logs yet. const isValid = await validationPromise; expect(isValid).toBe(true); // As the split existed, it will resolve to true. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It was valid so no logs. - expect(loggerMock.error.mock.calls.length).toBe(0); // It was valid so no logs. + expect(loggerMock.warn).not.toBeCalled(); // It was valid so no logs. + expect(loggerMock.error).not.toBeCalled(); // It was valid so no logs. // Second round, a TT that does not exist on the asnyc storage splitsCacheMock.trafficTypeExists.mockClear(); @@ -94,12 +91,12 @@ describe('validateTrafficTypeExistance', () => { const validationPromise2 = validateTrafficTypeExistance(loggerMock, readinessManagerMock, splitsCacheMock, STANDALONE_MODE, TEST_NOT_EXISTENT_ASYNC_TT, 'test_method_z'); expect(thenable(validationPromise2)).toBe(true); // If the storage is async, it should also return a promise. expect(splitsCacheMock.trafficTypeExists.mock.calls).toEqual([[TEST_NOT_EXISTENT_ASYNC_TT]]); // If the SDK is in condition to validate, it checks that TT existance with the async storage. - expect(loggerMock.warn.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. - expect(loggerMock.error.mock.calls.length).toBe(0); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.warn).not.toBeCalled(); // We are still fetching the data from the storage, no logs yet. + expect(loggerMock.error).not.toBeCalled(); // We are still fetching the data from the storage, no logs yet. const isValid2 = await validationPromise2; expect(isValid2).toBe(false); // As the split is not on the storage, it will resolve to false, failing the validation.. - expect(loggerMock.warn.mock.calls).toEqual([[`test_method_z: ${errorMsgs.NOT_EXISTENT_TT(TEST_NOT_EXISTENT_ASYNC_TT)}`]]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. - expect(loggerMock.error.mock.calls.length).toBe(0); // It logged a warning so no errors should be logged. + expect(loggerMock.warn).toBeCalledWith(WARN_NOT_EXISTENT_TT, ['test_method_z', TEST_NOT_EXISTENT_ASYNC_TT]); // If the SDK is in condition to validate but the TT does not exist in the storage, it will log the expected warning. + expect(loggerMock.error).not.toBeCalled(); // It logged a warning so no errors should be logged. }); }); diff --git a/src/utils/inputValidation/attributes.ts b/src/utils/inputValidation/attributes.ts index d40f21db..e45f67c0 100644 --- a/src/utils/inputValidation/attributes.ts +++ b/src/utils/inputValidation/attributes.ts @@ -1,13 +1,13 @@ import { isObject } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { ERROR_13 } from '../../logger/constants'; +import { ERROR_NOT_PLAIN_OBJECT } from '../../logger/constants'; export function validateAttributes(log: ILogger, maybeAttrs: any, method: string): SplitIO.Attributes | undefined | false { // Attributes are optional if (isObject(maybeAttrs) || maybeAttrs == undefined) // eslint-disable-line eqeqeq return maybeAttrs; - log.error(ERROR_13, [method]); + log.error(ERROR_NOT_PLAIN_OBJECT, [method, 'attributes']); return false; } diff --git a/src/utils/inputValidation/event.ts b/src/utils/inputValidation/event.ts index f067b23e..03e79c9e 100644 --- a/src/utils/inputValidation/event.ts +++ b/src/utils/inputValidation/event.ts @@ -1,4 +1,4 @@ -import { ERROR_14, ERROR_15, ERROR_16, ERROR_17 } from '../../logger/constants'; +import { ERROR_EVENT_TYPE_FORMAT, ERROR_NULL, ERROR_INVALID, ERROR_EMPTY } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; @@ -6,14 +6,14 @@ const EVENT_TYPE_REGEX = /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/; export function validateEvent(log: ILogger, maybeEvent: any, method: string): string | false { if (maybeEvent == undefined) { // eslint-disable-line eqeqeq - log.error(ERROR_15, [method]); + log.error(ERROR_NULL, [method]); } else if (!isString(maybeEvent)) { - log.error(ERROR_16, [method]); + log.error(ERROR_INVALID, [method]); } else { // It is a string. if (maybeEvent.length === 0) { - log.error(ERROR_17, [method]); + log.error(ERROR_EMPTY, [method]); } else if (!EVENT_TYPE_REGEX.test(maybeEvent)) { - log.error(ERROR_14, [method, maybeEvent]); + log.error(ERROR_EVENT_TYPE_FORMAT, [method, maybeEvent]); } else { return maybeEvent; } diff --git a/src/utils/inputValidation/eventProperties.ts b/src/utils/inputValidation/eventProperties.ts index 6f195e09..8a599a97 100644 --- a/src/utils/inputValidation/eventProperties.ts +++ b/src/utils/inputValidation/eventProperties.ts @@ -1,7 +1,7 @@ import { isObject, shallowClone, isString, isFiniteNumber, isBoolean } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { ERROR_18, ERROR_19, WARN_12, WARN_13 } from '../../logger/constants'; +import { ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES } from '../../logger/constants'; const ECMA_SIZES = { NULL: 0, // While on the JSON it's going to occupy more space, we'll take it as 0 for the approximation. @@ -17,7 +17,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth if (maybeProperties == undefined) return { properties: null, size: BASE_EVENT_SIZE }; // eslint-disable-line eqeqeq if (!isObject(maybeProperties)) { - log.error(ERROR_18, [method]); + log.error(ERROR_NOT_PLAIN_OBJECT, [method, 'properties']); return { properties: false, size: BASE_EVENT_SIZE }; } @@ -30,7 +30,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth }; if (keys.length > MAX_PROPERTIES_AMOUNT) { - log.warn(WARN_13, [method]); + log.warn(WARN_TRIMMING_PROPERTIES, [method]); } for (let i = 0; i < keys.length; i++) { @@ -47,7 +47,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth clone[keys[i]] = null; val = null; isNullVal = true; - log.warn(WARN_12, [method, keys[i]]); + log.warn(WARN_SETTING_NULL, [method, keys[i]]); } if (isNullVal) output.size += ECMA_SIZES.NULL; @@ -56,7 +56,7 @@ export function validateEventProperties(log: ILogger, maybeProperties: any, meth else if (isStringVal) output.size += val.length * ECMA_SIZES.STRING; if (output.size > MAX_PROPERTIES_SIZE) { - log.error(ERROR_19, [method]); + log.error(ERROR_SIZE_EXCEEDED, [method]); output.properties = false; break; } diff --git a/src/utils/inputValidation/eventValue.ts b/src/utils/inputValidation/eventValue.ts index ef9f5c36..9b7bdd16 100644 --- a/src/utils/inputValidation/eventValue.ts +++ b/src/utils/inputValidation/eventValue.ts @@ -1,4 +1,4 @@ -import { ERROR_20 } from '../../logger/constants'; +import { ERROR_NOT_FINITE } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isFiniteNumber } from '../lang'; @@ -6,6 +6,6 @@ export function validateEventValue(log: ILogger, maybeValue: any, method: string if (isFiniteNumber(maybeValue) || maybeValue == undefined) // eslint-disable-line eqeqeq return maybeValue; - log.error(ERROR_20, [method]); + log.error(ERROR_NOT_FINITE, [method]); return false; } diff --git a/src/utils/inputValidation/key.ts b/src/utils/inputValidation/key.ts index f7ec064f..9068bed6 100644 --- a/src/utils/inputValidation/key.ts +++ b/src/utils/inputValidation/key.ts @@ -1,17 +1,17 @@ import { isObject, isString, isFiniteNumber, toString } from '../lang'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { ERROR_22, WARN_15, ERROR_25, ERROR_23, ERROR_24, ERROR_26 } from '../../logger/constants'; +import { ERROR_NULL, WARN_CONVERTING, ERROR_EMPTY, ERROR_TOO_LONG, ERROR_INVALID, ERROR_INVALID_KEY_OBJECT } from '../../logger/constants'; const KEY_MAX_LENGTH = 250; function validateKeyValue(log: ILogger, maybeKey: any, method: string, type: string): string | false { if (maybeKey == undefined) { // eslint-disable-line eqeqeq - log.error(ERROR_22, [method, type, type]); + log.error(ERROR_NULL, [method, type]); return false; } if (isFiniteNumber(maybeKey)) { - log.warn(WARN_15, [method, type, maybeKey]); + log.warn(WARN_CONVERTING, [method, type, maybeKey]); return toString(maybeKey); } if (isString(maybeKey)) { @@ -22,12 +22,12 @@ function validateKeyValue(log: ILogger, maybeKey: any, method: string, type: str if (maybeKey.length > 0 && maybeKey.length <= KEY_MAX_LENGTH) return maybeKey; if (maybeKey.length === 0) { - log.error(ERROR_25, [method, type]); + log.error(ERROR_EMPTY, [method, type]); } else if (maybeKey.length > KEY_MAX_LENGTH) { - log.error(ERROR_23, [method, type, type]); + log.error(ERROR_TOO_LONG, [method, type]); } } else { - log.error(ERROR_24, [method, type, type]); + log.error(ERROR_INVALID, [method, type]); } return false; @@ -43,7 +43,7 @@ export function validateKey(log: ILogger, maybeKey: any, method: string): SplitI matchingKey, bucketingKey }; - log.error(ERROR_26, [method]); + log.error(ERROR_INVALID_KEY_OBJECT, [method]); return false; } else { return validateKeyValue(log, maybeKey, method, 'key'); diff --git a/src/utils/inputValidation/split.ts b/src/utils/inputValidation/split.ts index 12064144..b7261604 100644 --- a/src/utils/inputValidation/split.ts +++ b/src/utils/inputValidation/split.ts @@ -1,4 +1,4 @@ -import { ERROR_22, ERROR_32, WARN_17, ERROR_33 } from '../../logger/constants'; +import { ERROR_NULL, ERROR_INVALID, WARN_TRIMMING, ERROR_EMPTY } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; @@ -7,19 +7,19 @@ const TRIMMABLE_SPACES_REGEX = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/; export function validateSplit(log: ILogger, maybeSplit: any, method: string, item = 'split name'): string | false { if (maybeSplit == undefined) { // eslint-disable-line eqeqeq - log.error(ERROR_22, [method, item, item]); + log.error(ERROR_NULL, [method, item]); } else if (!isString(maybeSplit)) { - log.error(ERROR_32, [method, item, item]); + log.error(ERROR_INVALID, [method, item]); } else { if (TRIMMABLE_SPACES_REGEX.test(maybeSplit)) { - log.warn(WARN_17, [method, item, maybeSplit]); + log.warn(WARN_TRIMMING, [method, item, maybeSplit]); maybeSplit = maybeSplit.trim(); } if (maybeSplit.length > 0) { return maybeSplit; } else { - log.error(ERROR_33, [method, item, item]); + log.error(ERROR_EMPTY, [method, item]); } } diff --git a/src/utils/inputValidation/splitExistance.ts b/src/utils/inputValidation/splitExistance.ts index b8798f84..ddafa767 100644 --- a/src/utils/inputValidation/splitExistance.ts +++ b/src/utils/inputValidation/splitExistance.ts @@ -1,7 +1,7 @@ import { SPLIT_NOT_FOUND } from '../labels'; import { IReadinessManager } from '../../readiness/types'; import { ILogger } from '../../logger/types'; -import { WARN_18 } from '../../logger/constants'; +import { WARN_NOT_EXISTENT_SPLIT } from '../../logger/constants'; /** * This is defined here and in this format mostly because of the logger and the fact that it's considered a validation at product level. @@ -10,7 +10,7 @@ import { WARN_18 } from '../../logger/constants'; export function validateSplitExistance(log: ILogger, readinessManager: IReadinessManager, splitName: string, labelOrSplitObj: any, method: string): boolean { if (readinessManager.isReady()) { // Only if it's ready we validate this, otherwise it may just be that the SDK is not ready yet. if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj == null) { - log.warn(WARN_18, [method, splitName]); + log.warn(WARN_NOT_EXISTENT_SPLIT, [method, splitName]); return false; } } diff --git a/src/utils/inputValidation/splits.ts b/src/utils/inputValidation/splits.ts index 6807d7da..ee381210 100644 --- a/src/utils/inputValidation/splits.ts +++ b/src/utils/inputValidation/splits.ts @@ -1,4 +1,4 @@ -import { ERROR_34 } from '../../logger/constants'; +import { ERROR_EMPTY_ARRAY } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { uniq } from '../lang'; import { validateSplit } from './split'; @@ -16,6 +16,6 @@ export function validateSplits(log: ILogger, maybeSplits: any, method: string, l if (validatedArray.length) return uniq(validatedArray); } - log.error(ERROR_34, [method, listName]); + log.error(ERROR_EMPTY_ARRAY, [method, listName]); return false; } diff --git a/src/utils/inputValidation/trafficType.ts b/src/utils/inputValidation/trafficType.ts index 189560e8..79f1eb02 100644 --- a/src/utils/inputValidation/trafficType.ts +++ b/src/utils/inputValidation/trafficType.ts @@ -1,4 +1,4 @@ -import { ERROR_35, ERROR_36, ERROR_37, WARN_19 } from '../../logger/constants'; +import { ERROR_NULL, ERROR_INVALID, ERROR_EMPTY, WARN_LOWERCASE_TRAFFIC_TYPE } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; @@ -6,15 +6,15 @@ const CAPITAL_LETTERS_REGEX = /[A-Z]/; export function validateTrafficType(log: ILogger, maybeTT: any, method: string): string | false { if (maybeTT == undefined) { // eslint-disable-line eqeqeq - log.error(ERROR_35, [method]); + log.error(ERROR_NULL, [method]); } else if (!isString(maybeTT)) { - log.error(ERROR_36, [method]); + log.error(ERROR_INVALID, [method]); } else { if (maybeTT.length === 0) { - log.error(ERROR_37, [method]); + log.error(ERROR_EMPTY, [method]); } else { if (CAPITAL_LETTERS_REGEX.test(maybeTT)) { - log.warn(WARN_19, [method]); + log.warn(WARN_LOWERCASE_TRAFFIC_TYPE, [method]); maybeTT = maybeTT.toLowerCase(); } diff --git a/src/utils/inputValidation/trafficTypeExistance.ts b/src/utils/inputValidation/trafficTypeExistance.ts index 79244801..eb64c0d3 100644 --- a/src/utils/inputValidation/trafficTypeExistance.ts +++ b/src/utils/inputValidation/trafficTypeExistance.ts @@ -5,10 +5,10 @@ import { IReadinessManager } from '../../readiness/types'; import { SDKMode } from '../../types'; import { MaybeThenable } from '../../dtos/types'; import { ILogger } from '../../logger/types'; -import { WARN_20 } from '../../logger/constants'; +import { WARN_NOT_EXISTENT_TT } from '../../logger/constants'; function logTTExistanceWarning(log: ILogger, maybeTT: string, method: string) { - log.warn(WARN_20, [method, maybeTT]); + log.warn(WARN_NOT_EXISTENT_TT, [method, maybeTT]); } /** From adfc9812a688740bc9c9f277f67a8b7f67523d7d Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 17 Mar 2021 16:41:53 -0300 Subject: [PATCH 38/58] update for review --- src/logger/messages/error.ts | 3 +-- src/logger/messages/warn.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index eb99b714..65461821 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -12,6 +12,7 @@ export const codesError: [number, string][] = [ [ERROR_11, 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'], [ERROR_12, 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'], [ERROR_21, 'Client has already been destroyed - no calls possible.'], + [ERROR_38, 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: "%s" or "%s". Defaulting to "%s" mode.'], [ERROR_39, 'Response status is not OK. Status: %s. URL: %s. Message: %s'], // input validation [ERROR_EVENT_TYPE_FORMAT, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], @@ -24,6 +25,4 @@ export const codesError: [number, string][] = [ [ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'], [ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'], [ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'], - // initialization / settings validation - [ERROR_INVALID_ENUM, '%s: you passed an invalid %s. It should be one of the following values: %s. Defaulting to "%s" mode.'], ]; diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index 9a9e1328..97aab2f9 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -12,10 +12,10 @@ export const codesWarn: [number, string][] = [ [WARN_9, 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'], [WARN_10, 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'], [WARN_11, 'splitio-client:event-tracker => Failed to queue %s'], + [WARN_14, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], // input validation [WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'], [WARN_TRIMMING_PROPERTIES, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], - [WARN_14, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], [WARN_CONVERTING, '%s: %s "%s" is not of type string, converting.'], [WARN_TRIMMING, '%s: %s "%s" has extra whitespace, trimming.'], [WARN_NOT_EXISTENT_SPLIT, '%s: split "%s" does not exist in this environment, please double check what splits exist in the web console.'], From d46e31f8b57d096420edb1e853cb55507cfed141 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 18 Mar 2021 10:55:04 -0300 Subject: [PATCH 39/58] polishing settings and readiness related log messages --- src/logger/constants.ts | 31 ++++++----- src/logger/messages/debug.ts | 5 +- src/logger/messages/error.ts | 12 ++-- src/logger/messages/errorNode.ts | 5 +- src/logger/messages/info.ts | 10 +++- src/logger/messages/warn.ts | 19 ++++--- .../__tests__/sdkReadinessManager.spec.ts | 21 +++---- src/readiness/sdkReadinessManager.ts | 10 ++-- src/sdkClient/clientInputValidation.ts | 4 +- src/sdkClient/sdkClientMethodCS.ts | 2 +- src/sdkManager/index.ts | 6 +- .../polling/syncTasks/segmentsSyncTask.ts | 4 +- .../inputValidation/__tests__/apiKey.spec.ts | 55 ++++++++----------- .../__tests__/isOperational.spec.ts | 37 +++++++------ src/utils/inputValidation/apiKey.ts | 14 +++-- src/utils/inputValidation/isOperational.ts | 8 +-- .../__tests__/splitFilters.spec.ts | 35 +++++------- .../settingsValidation/impressionsMode.ts | 4 +- .../settingsValidation/integrations/common.ts | 4 +- src/utils/settingsValidation/splitFilters.ts | 12 ++-- .../settingsValidation/storage/storageCS.ts | 4 +- 21 files changed, 152 insertions(+), 150 deletions(-) diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 3e4904be..860c7c18 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -38,7 +38,7 @@ export const DEBUG_47 = 47; export const DEBUG_48 = 48; export const DEBUG_49 = 49; export const DEBUG_50 = 50; -export const DEBUG_51 = 51; +export const DEBUG_SPLITS_FILTER = 51; // browser export const DEBUG_26 = 26; @@ -59,7 +59,7 @@ export const DEBUG_38 = 38; // @TODO remove since we already log it in syncTask // commons export const ERROR_0 = 300; export const ERROR_2 = 302; -export const ERROR_3 = 303; +export const ERROR_CLIENT_LISTENER = 303; export const ERROR_4 = 304; export const ERROR_5 = 305; export const ERROR_7 = 307; @@ -71,24 +71,24 @@ export const ERROR_EVENT_TYPE_FORMAT = 314; export const ERROR_NOT_PLAIN_OBJECT = 318; export const ERROR_SIZE_EXCEEDED = 319; export const ERROR_NOT_FINITE = 320; -export const ERROR_21 = 321; +export const ERROR_CLIENT_DESTROYED = 321; export const ERROR_NULL = 322; export const ERROR_TOO_LONG = 323; export const ERROR_INVALID_KEY_OBJECT = 326; export const ERROR_INVALID = 332; export const ERROR_EMPTY = 333; export const ERROR_EMPTY_ARRAY = 334; -export const ERROR_INVALID_ENUM = 338; +export const ERROR_INVALID_IMPRESSIONS_MODE = 338; export const ERROR_39 = 339; // node export const ERROR_1 = 301; -export const ERROR_8 = 308; +export const ERROR_API_KEY_INVALID = 308; export const ERROR_6 = 306; // commons -export const INFO_0 = 100; -export const INFO_1 = 101; +export const INFO_CLIENT_READY_FROM_CACHE = 100; +export const INFO_CLIENT_READY = 101; export const INFO_2 = 102; export const INFO_3 = 103; export const INFO_4 = 104; @@ -113,7 +113,7 @@ export const INFO_21 = 121; // commons export const WARN_0 = 200; export const WARN_1 = 201; -export const WARN_2 = 202; +export const WARN_CLIENT_NO_LISTENER = 202; export const WARN_4 = 204; export const WARN_5 = 205; export const WARN_6 = 206; @@ -124,18 +124,21 @@ export const WARN_10 = 210; export const WARN_11 = 211; export const WARN_SETTING_NULL = 212; export const WARN_TRIMMING_PROPERTIES = 213; -export const WARN_14 = 214; +export const WARN_CLIENT_NOT_READY = 214; export const WARN_CONVERTING = 215; export const WARN_TRIMMING = 217; export const WARN_NOT_EXISTENT_SPLIT = 218; export const WARN_LOWERCASE_TRAFFIC_TYPE = 219; export const WARN_NOT_EXISTENT_TT = 220; -export const WARN_21 = 221; -export const WARN_22 = 222; -export const WARN_23 = 223; -export const WARN_24 = 224; -export const WARN_25 = 225; +export const WARN_INTEGRATION_INVALID = 221; +export const WARN_SPLITS_FILTER_IGNORED = 222; +export const WARN_SPLITS_FILTER_INVALID = 223; +export const WARN_SPLITS_FILTER_EMPTY = 224; +export const WARN_STORAGE_INVALID = 225; export const WARN_API_KEY = 226; // node export const WARN_3 = 203; + +// Log tags or categories +export const SETTINGS_LB = 'settings'; diff --git a/src/logger/messages/debug.ts b/src/logger/messages/debug.ts index dec2f5b7..91cf7e71 100644 --- a/src/logger/messages/debug.ts +++ b/src/logger/messages/debug.ts @@ -1,4 +1,4 @@ -import { DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_31, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_51 } from '../constants'; +import { DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_31, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_SPLITS_FILTER, SETTINGS_LB } from '../constants'; export const codesDebug: [number, string][] = [ [DEBUG_0, 'splitio-engine:combiner => [andCombiner] evaluates to %s'], @@ -40,5 +40,6 @@ export const codesDebug: [number, string][] = [ [DEBUG_48, 'splitio-sync:task => Running %s'], [DEBUG_49, 'splitio-sync:task => Stopping %s'], [DEBUG_50, 'splitio-client:impressions-tracker => Successfully stored %s impression%s.'], - [DEBUG_51, 'Factory instantiation: splits filtering criteria is "%s".'] + // initialization / settings validation + [DEBUG_SPLITS_FILTER, SETTINGS_LB+': splits filtering criteria is "%s".'] ]; diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index 65461821..f48bd7ab 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -1,9 +1,8 @@ -import { ERROR_0, ERROR_2, ERROR_3, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_21, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_ENUM, ERROR_39 } from '../constants'; +import { ERROR_0, ERROR_2, ERROR_CLIENT_LISTENER, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_CLIENT_DESTROYED, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_IMPRESSIONS_MODE, ERROR_39, SETTINGS_LB } from '../constants'; export const codesError: [number, string][] = [ [ERROR_0, 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'], [ERROR_2, 'splitio-utils:logger => Invalid Log Level - No changes to the logs will be applied.'], - [ERROR_3, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], [ERROR_4, 'splitio => Manager instance is not available. Provide the manager module on settings.'], [ERROR_5, 'splitio-services:service => %s The SDK will not get ready.'], [ERROR_7, 'splitio-producer:offline => There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], @@ -11,9 +10,10 @@ export const codesError: [number, string][] = [ [ERROR_10, 'splitio-sync:push-manager => Failed to authenticate for streaming. Error: "%s".'], [ERROR_11, 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'], [ERROR_12, 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'], - [ERROR_21, 'Client has already been destroyed - no calls possible.'], - [ERROR_38, 'splitio-settings => You passed an invalid impressionsMode, impressionsMode should be one of the following values: "%s" or "%s". Defaulting to "%s" mode.'], - [ERROR_39, 'Response status is not OK. Status: %s. URL: %s. Message: %s'], + [ERROR_39, 'splitio-services:service => Response status is not OK. Status: %s. URL: %s. Message: %s'], + // client status + [ERROR_CLIENT_LISTENER, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], + [ERROR_CLIENT_DESTROYED, '%s: Client has already been destroyed - no calls possible.'], // input validation [ERROR_EVENT_TYPE_FORMAT, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], [ERROR_NOT_PLAIN_OBJECT, '%s: %s must be a plain object.'], @@ -25,4 +25,6 @@ export const codesError: [number, string][] = [ [ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'], [ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'], [ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'], + // initialization / settings validation + [ERROR_INVALID_IMPRESSIONS_MODE, SETTINGS_LB + ': you passed an invalid "impressionsMode". It should be one of the following values: %s. Defaulting to "%s" mode.'], ]; diff --git a/src/logger/messages/errorNode.ts b/src/logger/messages/errorNode.ts index 8e3adc6d..54091cca 100644 --- a/src/logger/messages/errorNode.ts +++ b/src/logger/messages/errorNode.ts @@ -1,7 +1,8 @@ -import { ERROR_1, ERROR_8, ERROR_6 } from '../constants'; +import { ERROR_1, ERROR_API_KEY_INVALID, ERROR_6, SETTINGS_LB } from '../constants'; export const codesErrorNode: [number, string][] = [ [ERROR_1, 'splitio-client:cleanup => Error with Split graceful shutdown: %s'], - [ERROR_8, 'splitio-sync:segment-changes => Factory instantiation: you passed a Browser type authorizationKey, please grab an Api Key from the Split web console that is of type SDK.'], [ERROR_6, 'splitio-offline:splits-fetcher => Ignoring entry on YAML since the format is incorrect.'], + // initialization / settings validation + [ERROR_API_KEY_INVALID, SETTINGS_LB+': you passed a Client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.'], ]; diff --git a/src/logger/messages/info.ts b/src/logger/messages/info.ts index e2fed1a3..ddb05a58 100644 --- a/src/logger/messages/info.ts +++ b/src/logger/messages/info.ts @@ -1,8 +1,12 @@ -import { INFO_0, INFO_1, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21 } from '../constants'; +import { INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21 } from '../constants'; + +const READY_MSG = 'Split SDK is ready'; export const codesInfo: [number, string][] = [ - [INFO_0, 'Split SDK is ready from cache.'], - [INFO_1, 'Split SDK is ready.'], + // client status + [INFO_CLIENT_READY_FROM_CACHE, READY_MSG + ' from cache'], + [INFO_CLIENT_READY, READY_MSG], + [INFO_2, 'splitio-client => Split: %s. Key: %s. Evaluation: %s. Label: %s'], [INFO_3, 'splitio-client => Queueing corresponding impression.'], [INFO_4, 'splitio => New shared client instance created.'], diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index 97aab2f9..e24b021a 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -1,9 +1,8 @@ -import { WARN_0, WARN_1, WARN_2, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, WARN_14, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_21, WARN_22, WARN_23, WARN_24, WARN_25, WARN_API_KEY } from '../constants'; +import { WARN_0, WARN_1, WARN_CLIENT_NO_LISTENER, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, WARN_CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, SETTINGS_LB } from '../constants'; export const codesWarn: [number, string][] = [ [WARN_0, 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'], [WARN_1, 'splitio-engine:value => Defined attribute [%s], no attributes received.'], - [WARN_2, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], [WARN_4, 'splitio-sync:my-segments => Retrying download of segments #%s. Reason: %s'], [WARN_5, 'splitio-sync:split-changes => Error while doing fetch of Splits. %s'], [WARN_6, 'splitio-sync:sse-handler => Error parsing SSE error notification: %s'], @@ -12,7 +11,9 @@ export const codesWarn: [number, string][] = [ [WARN_9, 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'], [WARN_10, 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'], [WARN_11, 'splitio-client:event-tracker => Failed to queue %s'], - [WARN_14, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], + // client status + [WARN_CLIENT_NOT_READY, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], + [WARN_CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], // input validation [WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'], [WARN_TRIMMING_PROPERTIES, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], @@ -22,10 +23,10 @@ export const codesWarn: [number, string][] = [ [WARN_LOWERCASE_TRAFFIC_TYPE, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], [WARN_NOT_EXISTENT_TT, '%s: traffic type "%s" does not have any corresponding split in this environment, make sure you\'re tracking your events to a valid traffic type defined in the web console.'], // initialization / settings validation - [WARN_21, 'splitio-settings => %s integration %s at settings %s invalid. %s'], - [WARN_22, 'Factory instantiation: split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'], - [WARN_23, 'Factory instantiation: split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'], - [WARN_24, 'Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.'], - [WARN_25, 'splitio-settings => The provided storage is invalid. Fallbacking into default MEMORY storage'], - [WARN_API_KEY, 'Factory instantiation: %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'] + [WARN_INTEGRATION_INVALID, SETTINGS_LB+': %s integration %s at settings %s invalid. %s'], + [WARN_SPLITS_FILTER_IGNORED, SETTINGS_LB+': split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'], + [WARN_SPLITS_FILTER_INVALID, SETTINGS_LB+': split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'], + [WARN_SPLITS_FILTER_EMPTY, SETTINGS_LB+': splitFilters configuration must be a non-empty array of filter objects.'], + [WARN_STORAGE_INVALID, SETTINGS_LB+': The provided storage is invalid. Fallbacking into default MEMORY storage'], + [WARN_API_KEY, SETTINGS_LB+': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'] ]; diff --git a/src/readiness/__tests__/sdkReadinessManager.spec.ts b/src/readiness/__tests__/sdkReadinessManager.spec.ts index 7034592c..cde58e8f 100644 --- a/src/readiness/__tests__/sdkReadinessManager.spec.ts +++ b/src/readiness/__tests__/sdkReadinessManager.spec.ts @@ -4,6 +4,7 @@ import { IEventEmitter } from '../../types'; import { SDK_READY, SDK_READY_FROM_CACHE, SDK_READY_TIMED_OUT, SDK_UPDATE } from '../constants'; import sdkReadinessManagerFactory from '../sdkReadinessManager'; import { IReadinessManager } from '../types'; +import { ERROR_CLIENT_LISTENER, INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, WARN_CLIENT_NO_LISTENER } from '../../logger/constants'; const EventEmitterMock = jest.fn(() => ({ on: jest.fn(), @@ -81,7 +82,7 @@ describe('SDK Readiness Manager - Event emitter', () => { const readyFromCacheEventCB = gateMock.once.mock.calls[2][1]; readyFromCacheEventCB(); expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY_FROM_CACHE event fires, we get a info message. - expect(loggerMock.info.mock.calls[0]).toEqual(['Split SDK is ready from cache.']); // Telling us the SDK is ready to be used with data from cache. + expect(loggerMock.info).toBeCalledWith(INFO_CLIENT_READY_FROM_CACHE); // Telling us the SDK is ready to be used with data from cache. }); test('The event callbacks should work as expected - SDK_READY emits with no callbacks', () => { @@ -93,21 +94,21 @@ describe('SDK Readiness Manager - Event emitter', () => { emitReadyEvent(sdkReadinessManager.readinessManager); expect(loggerMock.warn.mock.calls.length).toBe(1); // If the SDK_READY event fires and we have no callbacks for it (neither event nor ready promise) we get a warning. - expect(loggerMock.warn.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // Telling us there were no listeners and evaluations before this point may have been incorrect. + expect(loggerMock.warn).toBeCalledWith(WARN_CLIENT_NO_LISTENER); // Telling us there were no listeners and evaluations before this point may have been incorrect. expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY event fires, we get a info message. - expect(loggerMock.info.mock.calls[0]).toEqual(['Split SDK is ready.']); // Telling us the SDK is ready. + expect(loggerMock.info).toBeCalledWith(INFO_CLIENT_READY); // Telling us the SDK is ready. // Now it's marked as ready. addListenerCB('this event we do not care'); expect(loggerMock.error.mock.calls.length).toBe(0); // Now if we add a listener to an event unrelated with readiness, we get no errors logged. addListenerCB(SDK_READY); - expect(loggerMock.error.mock.calls).toEqual([['A listener was added for SDK_READY on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY we get the corresponding warning. + expect(loggerMock.error).toBeCalledWith(ERROR_CLIENT_LISTENER, ['SDK_READY']); // If we try to add a listener for the already emitted SDK_READY event, we get the corresponding error. loggerMock.error.mockClear(); addListenerCB(SDK_READY_TIMED_OUT); - expect(loggerMock.error.mock.calls).toEqual([['A listener was added for SDK_READY_TIMED_OUT on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.']]); // If we try to add a listener to SDK_READY_TIMED_OUT we get the corresponding warning. + expect(loggerMock.error).toBeCalledWith(ERROR_CLIENT_LISTENER, ['SDK_READY_TIMED_OUT']); // If we try to add a listener for the already emitted SDK_READY_TIMED_OUT event, we get the corresponding error. }); test('The event callbacks should work as expected - SDK_READY emits with callbacks', () => { @@ -125,7 +126,7 @@ describe('SDK Readiness Manager - Event emitter', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY event fires, we get a info message. - expect(loggerMock.info.mock.calls[0]).toEqual(['Split SDK is ready.']); // Telling us the SDK is ready. + expect(loggerMock.info).toBeCalledWith(INFO_CLIENT_READY); // Telling us the SDK is ready. }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { @@ -145,7 +146,7 @@ describe('SDK Readiness Manager - Event emitter', () => { removeListenerCB(SDK_READY); emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls[0]).toEqual(['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']); // We get the warning. + expect(loggerMock.warn).toBeCalledWith(WARN_CLIENT_NO_LISTENER); // We get the warning. }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { @@ -271,7 +272,7 @@ describe('SDK Readiness Manager - Ready promise', () => { const readyEventCB = sdkReadinessManager.readinessManager.gate.once.mock.calls[0][1]; readyEventCB(); - expect(loggerMock.warn.mock.calls).toEqual([['No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.']]); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise. + expect(loggerMock.warn).toBeCalledWith(WARN_CLIENT_NO_LISTENER); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise. loggerMock.warn.mockClear(); readyPromise.then(() => { @@ -282,7 +283,7 @@ describe('SDK Readiness Manager - Ready promise', () => { }); readyEventCB(); - expect(loggerMock.warn.mock.calls.length).toBe(0); // But if we have a listener there are no warnings. + expect(loggerMock.warn).not.toBeCalled(); // But if we have a listener there are no warnings. }); test('.ready() rejected promises have a default onRejected handler that just logs the error', (done) => { @@ -295,7 +296,7 @@ describe('SDK Readiness Manager - Ready promise', () => { () => { throw new Error('It should be a promise that was rejected on SDK_READY_TIMED_OUT, not resolved.'); } ); - expect(loggerMock.error.mock.calls.length === 0).toBe(true); // not called until promise is rejected + expect(loggerMock.error).not.toBeCalled(); // not called until promise is rejected setTimeout(() => { expect(loggerMock.error.mock.calls).toEqual([[timeoutErrorMessage]]); // If we don\'t handle the rejected promise, an error is logged. diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index d2bfffe7..f1ada0fa 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -5,7 +5,7 @@ import { ISdkReadinessManager } from './types'; import { IEventEmitter } from '../types'; import { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from './constants'; import { ILogger } from '../logger/types'; -import { ERROR_3, INFO_0, INFO_1, WARN_2 } from '../logger/constants'; +import { ERROR_CLIENT_LISTENER, INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, WARN_CLIENT_NO_LISTENER } from '../logger/constants'; const NEW_LISTENER_EVENT = 'newListener'; const REMOVE_LISTENER_EVENT = 'removeListener'; @@ -35,7 +35,7 @@ export default function sdkReadinessManagerFactory( readinessManager.gate.on(NEW_LISTENER_EVENT, (event: any) => { if (event === SDK_READY || event === SDK_READY_TIMED_OUT) { if (readinessManager.isReady()) { - log.error(ERROR_3, [event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT']); + log.error(ERROR_CLIENT_LISTENER, [event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT']); } else if (event === SDK_READY) { readyCbCount++; } @@ -46,7 +46,7 @@ export default function sdkReadinessManagerFactory( const readyPromise = generateReadyPromise(); readinessManager.gate.once(SDK_READY_FROM_CACHE, () => { - log.info(INFO_0); + log.info(INFO_CLIENT_READY_FROM_CACHE); }); // default onRejected handler, that just logs the error, if ready promise doesn't have one. @@ -57,9 +57,9 @@ export default function sdkReadinessManagerFactory( function generateReadyPromise() { const promise = promiseWrapper(new Promise((resolve, reject) => { readinessManager.gate.once(SDK_READY, () => { - log.info(INFO_1); + log.info(INFO_CLIENT_READY); - if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn(WARN_2); + if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn(WARN_CLIENT_NO_LISTENER); resolve(); }); readinessManager.gate.once(SDK_READY_TIMED_OUT, reject); diff --git a/src/sdkClient/clientInputValidation.ts b/src/sdkClient/clientInputValidation.ts index 93e7fca8..c0fc26bf 100644 --- a/src/sdkClient/clientInputValidation.ts +++ b/src/sdkClient/clientInputValidation.ts @@ -32,7 +32,7 @@ export default function clientInputValidationDecorator Promise @@ -97,7 +97,7 @@ function segmentChangesUpdaterFactory( if (error.statusCode === 403) { // @TODO although factory status is destroyed, synchronization is not stopped readiness.destroy(); - log.error(ERROR_8); + log.error(ERROR_API_KEY_INVALID); } return false; diff --git a/src/utils/inputValidation/__tests__/apiKey.spec.ts b/src/utils/inputValidation/__tests__/apiKey.spec.ts index 23d75893..c1cbb25d 100644 --- a/src/utils/inputValidation/__tests__/apiKey.spec.ts +++ b/src/utils/inputValidation/__tests__/apiKey.spec.ts @@ -1,26 +1,21 @@ +import { ERROR_EMPTY, ERROR_NULL, ERROR_INVALID, WARN_API_KEY } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateApiKey, validateAndTrackApiKey, releaseApiKey } from '../apiKey'; -const errorMsgs = { - WRONG_TYPE_API_KEY: 'Factory instantiation: you passed an invalid api_key, api_key must be a non-empty string.', - EMPTY_API_KEY: 'Factory instantiation: you passed an empty api_key, api_key must be a non-empty string.', - NULL_API_KEY: 'Factory instantiation: you passed a null or undefined api_key, api_key must be a non-empty string.' -}; - const invalidKeys = [ - { key: '', msg: errorMsgs.EMPTY_API_KEY }, - { key: null, msg: errorMsgs.NULL_API_KEY }, - { key: undefined, msg: errorMsgs.NULL_API_KEY }, - { key: () => { }, msg: errorMsgs.WRONG_TYPE_API_KEY }, - { key: new Promise(r => r()), msg: errorMsgs.WRONG_TYPE_API_KEY }, - { key: Symbol('asd'), msg: errorMsgs.WRONG_TYPE_API_KEY }, - { key: [], msg: errorMsgs.WRONG_TYPE_API_KEY }, - { key: true, msg: errorMsgs.WRONG_TYPE_API_KEY }, - { key: NaN, msg: errorMsgs.WRONG_TYPE_API_KEY }, - { key: Infinity, msg: errorMsgs.WRONG_TYPE_API_KEY }, - { key: -Infinity, msg: errorMsgs.WRONG_TYPE_API_KEY }, - { key: {}, msg: errorMsgs.WRONG_TYPE_API_KEY } + { key: '', msg: ERROR_EMPTY }, + { key: null, msg: ERROR_NULL }, + { key: undefined, msg: ERROR_NULL }, + { key: () => { }, msg: ERROR_INVALID }, + { key: new Promise(r => r()), msg: ERROR_INVALID }, + { key: Symbol('asd'), msg: ERROR_INVALID }, + { key: [], msg: ERROR_INVALID }, + { key: true, msg: ERROR_INVALID }, + { key: NaN, msg: ERROR_INVALID }, + { key: Infinity, msg: ERROR_INVALID }, + { key: -Infinity, msg: ERROR_INVALID }, + { key: {}, msg: ERROR_INVALID } ]; describe('validateApiKey', () => { @@ -31,7 +26,7 @@ describe('validateApiKey', () => { const validApiKey = 'qjok3snti4dgsticade5hfphmlucarsflv14'; expect(validateApiKey(loggerMock, validApiKey)).toBe(validApiKey); // It should return the passed string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. }); test('Should return false and log error if the api key is invalid', () => { @@ -57,13 +52,11 @@ describe('validateAndTrackApiKey', () => { const validApiKey3 = '84ynbsnti4dgsticade5hfphmlucars92uih'; expect(validateAndTrackApiKey(loggerMock, validApiKey1)).toBe(validApiKey1); - expect(loggerMock.warn.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. + expect(loggerMock.warn).not.toBeCalled(); // If this is the first api key we are registering, there is no warning. expect(validateAndTrackApiKey(loggerMock, validApiKey2)).toBe(validApiKey2); - expect(loggerMock.warn.mock.calls).toEqual([['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a new api key, we get a warning. - expect(validateAndTrackApiKey(loggerMock, validApiKey3)).toBe(validApiKey3); - expect(loggerMock.warn.mock.calls[0]).toEqual(['Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']); // We register a new api key, we get a warning. + expect(loggerMock.warn).toBeCalledWith(WARN_API_KEY, ['an instance of the Split factory']); // we get a warning when we register a new api key. // We will release the used keys and expect no warnings next time. releaseApiKey(validApiKey1); @@ -73,7 +66,7 @@ describe('validateAndTrackApiKey', () => { loggerMock.mockClear(); expect(validateAndTrackApiKey(loggerMock, validApiKey1)).toBe(validApiKey1); - expect(loggerMock.warn.mock.calls.length).toBe(0); // If all the keys were released and we try again, there is no warning. + expect(loggerMock.warn).not.toBeCalled(); // If all the keys were released and we try again, there is no warning. releaseApiKey(validApiKey1); // clean up the cache of api keys for next test }); @@ -82,7 +75,7 @@ describe('validateAndTrackApiKey', () => { const validApiKey = '84ynbsnti4dgsticade5hfphmlucars92uih'; expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); - expect(loggerMock.warn.mock.calls.length).toBe(0); // If this is the first api key we are registering, there is no warning. + expect(loggerMock.warn).not.toBeCalled(); // If this is the first api key we are registering, there is no warning. expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); @@ -93,10 +86,10 @@ describe('validateAndTrackApiKey', () => { expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); expect(loggerMock.warn.mock.calls).toEqual([ - ['Factory instantiation: You already have 1 factory with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'], // We register a the same api key again, we get a warning with the number of instances we have. - ['Factory instantiation: You already have 2 factories with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'], // We register a the same api key again, we get a warning with the number of instances we have. - ['Factory instantiation: You already have 3 factories with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.'] // We register a the same api key again, we get a warning with the number of instances we have. - ]); + [WARN_API_KEY, ['1 factory with this API Key']], + [WARN_API_KEY, ['2 factories with this API Key']], + [WARN_API_KEY, ['3 factories with this API Key']] + ]); // We get a warning each time we register the same api key, with the number of instances we have. // We will release the used api key leaving only 1 "use" on the cache. releaseApiKey(validApiKey); @@ -107,7 +100,7 @@ describe('validateAndTrackApiKey', () => { // So we get the warning again. expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); - expect(loggerMock.warn.mock.calls).toEqual([['Factory instantiation: You already have 1 factory with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.']]); // We register a the same api key again, we get a warning with the number of instances we have. + expect(loggerMock.warn).toBeCalledWith(WARN_API_KEY, ['1 factory with this API Key']); // Leave it with 0 releaseApiKey(validApiKey); @@ -116,7 +109,7 @@ describe('validateAndTrackApiKey', () => { loggerMock.mockClear(); expect(validateAndTrackApiKey(loggerMock, validApiKey)).toBe(validApiKey); - expect(loggerMock.warn.mock.calls.length).toBe(0); // s users, there is no warning when we use it again. + expect(loggerMock.warn).not.toBeCalled(); // s users, there is no warning when we use it again. releaseApiKey(validApiKey); // clean up the cache just in case a new test is added }); diff --git a/src/utils/inputValidation/__tests__/isOperational.spec.ts b/src/utils/inputValidation/__tests__/isOperational.spec.ts index e5ab45b8..0d32547a 100644 --- a/src/utils/inputValidation/__tests__/isOperational.spec.ts +++ b/src/utils/inputValidation/__tests__/isOperational.spec.ts @@ -1,3 +1,4 @@ +import { WARN_CLIENT_NOT_READY, ERROR_CLIENT_DESTROYED } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateIfNotDestroyed, validateIfOperational } from '../isOperational'; @@ -11,19 +12,19 @@ describe('validateIfNotDestroyed', () => { // @ts-ignore expect(validateIfNotDestroyed(loggerMock, readinessManagerMock)).toBe(true); // It should return true if the client is operational (it is NOT destroyed). - expect(readinessManagerMock.isDestroyed.mock.calls.length).toBe(1); // It checks for destroyed status using the context. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // Should not log any warnings. + expect(readinessManagerMock.isDestroyed).toBeCalledTimes(1); // It checks for destroyed status using the context. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).not.toBeCalled(); // Should not log any warnings. }); test('Should return false and log error if attributes map is invalid', () => { const readinessManagerMock = { isDestroyed: jest.fn(() => true) }; // @ts-ignore - expect(validateIfNotDestroyed(loggerMock, readinessManagerMock)).toBe(false); // It should return false if the client is NOT operational (it is destroyed). - expect(readinessManagerMock.isDestroyed.mock.calls.length).toBe(1); // It checks for destroyed status using the context. - expect(loggerMock.error.mock.calls).toEqual([['Client has already been destroyed - no calls possible.']]); // Should log an error. - expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. + expect(validateIfNotDestroyed(loggerMock, readinessManagerMock, 'test_method')).toBe(false); // It should return false if the client is NOT operational (it is destroyed). + expect(readinessManagerMock.isDestroyed).toBeCalledTimes(1); // It checks for destroyed status using the context. + expect(loggerMock.error).toBeCalledWith(ERROR_CLIENT_DESTROYED, ['test_method']); // Should log an error. + expect(loggerMock.warn).not.toBeCalled(); // But it should not log any warnings. }); }); @@ -34,9 +35,9 @@ describe('validateIfOperational', () => { // @ts-ignore expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready. - expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for readiness status using the context. - expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. + expect(readinessManagerMock.isReady).toBeCalledTimes(1); // It checks for readiness status using the context. + expect(loggerMock.warn).not.toBeCalled(); // But it should not log any warnings. + expect(loggerMock.error).not.toBeCalled(); // But it should not log any errors. }); test('Should return true and log nothing if the SDK was ready from cache.', () => { @@ -44,10 +45,10 @@ describe('validateIfOperational', () => { // @ts-ignore expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(true); // It should return true if SDK was ready. - expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for SDK_READY status. - expect(readinessManagerMock.isReadyFromCache.mock.calls.length).toBe(1); // It checks for SDK_READY_FROM_CACHE status. - expect(loggerMock.warn.mock.calls.length).toBe(0); // But it should not log any warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. + expect(readinessManagerMock.isReady).toBeCalledTimes(1); // It checks for SDK_READY status. + expect(readinessManagerMock.isReadyFromCache).toBeCalledTimes(1); // It checks for SDK_READY_FROM_CACHE status. + expect(loggerMock.warn).not.toBeCalled(); // But it should not log any warnings. + expect(loggerMock.error).not.toBeCalled(); // But it should not log any errors. }); test('Should return false and log a warning if the SDK was not ready.', () => { @@ -55,9 +56,9 @@ describe('validateIfOperational', () => { // @ts-ignore expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(false); // It should return true if SDK was ready. - expect(readinessManagerMock.isReady.mock.calls.length).toBe(1); // It checks for SDK_READY status. - expect(readinessManagerMock.isReadyFromCache.mock.calls.length).toBe(1); // It checks for SDK_READY_FROM_CACHE status. - expect(loggerMock.warn.mock.calls).toEqual([['test_method: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.']]); // It should log the expected warning. - expect(loggerMock.error.mock.calls.length).toBe(0); // But it should not log any errors. + expect(readinessManagerMock.isReady).toBeCalledTimes(1); // It checks for SDK_READY status. + expect(readinessManagerMock.isReadyFromCache).toBeCalledTimes(1); // It checks for SDK_READY_FROM_CACHE status. + expect(loggerMock.warn).toBeCalledWith(WARN_CLIENT_NOT_READY, ['test_method']); // It should log the expected warning. + expect(loggerMock.error).not.toBeCalled(); // But it should not log any errors. }); }); diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index da2bdbbb..c4e3d2ff 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -1,19 +1,21 @@ -import { ERROR_API_KEY, WARN_API_KEY } from '../../logger/constants'; +import { ERROR_NULL, ERROR_EMPTY, ERROR_INVALID, WARN_API_KEY, SETTINGS_LB } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; +const item = 'api_key'; + /** validates the given api key */ export function validateApiKey(log: ILogger, maybeApiKey: any): string | false { let apiKey: string | false = false; if (maybeApiKey == undefined) { // eslint-disable-line eqeqeq - log.error(ERROR_API_KEY, ['you passed a null or undefined api_key']); + log.error(ERROR_NULL, [SETTINGS_LB, item]); } else if (isString(maybeApiKey)) { if (maybeApiKey.length > 0) apiKey = maybeApiKey; else - log.error(ERROR_API_KEY, ['you passed an empty api_key']); + log.error(ERROR_EMPTY, [SETTINGS_LB, item]); } else { - log.error(ERROR_API_KEY, ['you passed an invalid api_key']); + log.error(ERROR_INVALID, [SETTINGS_LB, item]); } return apiKey; @@ -31,10 +33,10 @@ export function validateAndTrackApiKey(log: ILogger, maybeApiKey: any): string | // If this key is not present, only warning scenarios is that we have factories for other keys. usedKeysMap[apiKey] = 1; if (Object.keys(usedKeysMap).length > 1) { - log.warn(WARN_API_KEY, ['You already have an instance of the Split factory. Make sure you definitely want this additional instance']); + log.warn(WARN_API_KEY, ['an instance of the Split factory']); } } else { - log.warn(WARN_API_KEY, [`You already have ${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key`]); + log.warn(WARN_API_KEY, [`${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key`]); usedKeysMap[apiKey]++; } } diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index 34ef4464..666b9d33 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -1,17 +1,17 @@ -import { ERROR_21, WARN_14 } from '../../logger/constants'; +import { ERROR_CLIENT_DESTROYED, WARN_CLIENT_NOT_READY } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { IReadinessManager } from '../../readiness/types'; -export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadinessManager): boolean { +export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadinessManager, method: string): boolean { if (!readinessManager.isDestroyed()) return true; - log.error(ERROR_21); + log.error(ERROR_CLIENT_DESTROYED, [method]); return false; } export function validateIfOperational(log: ILogger, readinessManager: IReadinessManager, method: string) { if (readinessManager.isReady() || readinessManager.isReadyFromCache()) return true; - log.warn(WARN_14, [method]); + log.warn(WARN_CLIENT_NOT_READY, [method]); return false; } diff --git a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts index d46117e5..6024ec2e 100644 --- a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts +++ b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts @@ -7,6 +7,7 @@ import { splitFilters, queryStrings, groupedFilters } from '../../../__tests__/m // Test target import { validateSplitFilters } from '../splitFilters'; +import { DEBUG_SPLITS_FILTER, ERROR_INVALID, ERROR_EMPTY_ARRAY, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY } from '../../../logger/constants'; describe('validateSplitFilters', () => { @@ -22,25 +23,17 @@ describe('validateSplitFilters', () => { expect(validateSplitFilters(loggerMock, undefined, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array expect(validateSplitFilters(loggerMock, null, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls.length === 0).toBe(true); + expect(loggerMock.warn).not.toBeCalled(); expect(validateSplitFilters(loggerMock, true, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls[0]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); - expect(validateSplitFilters(loggerMock, 15, STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls[1]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); - expect(validateSplitFilters(loggerMock, 'string', STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls[2]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); - expect(validateSplitFilters(loggerMock, [], STANDALONE_MODE)).toEqual(defaultOutput); // splitFilters ignored if not a non-empty array - expect(loggerMock.warn.mock.calls[3]).toEqual(['Factory instantiation: splitFilters configuration must be a non-empty array of filter objects.']); - - expect(validateSplitFilters(loggerMock, [{ type: 'byName', values: ['split_1'] }], CONSUMER_MODE)).toEqual(defaultOutput); - expect(loggerMock.warn.mock.calls[4]).toEqual(["Factory instantiation: split filters have been configured but will have no effect if mode is not 'standalone', since synchronization is being deferred to an external tool."]); + expect(validateSplitFilters(loggerMock, [{ type: 'byName', values: ['split_1'] }], CONSUMER_MODE)).toEqual(defaultOutput); // splitFilters ignored if not in 'standalone' mode + expect(loggerMock.warn.mock.calls).toEqual([[WARN_SPLITS_FILTER_EMPTY], [WARN_SPLITS_FILTER_EMPTY], [WARN_SPLITS_FILTER_EMPTY], [WARN_SPLITS_FILTER_EMPTY], [WARN_SPLITS_FILTER_IGNORED, ['standalone']]]); - expect(loggerMock.debug.mock.calls.length === 0).toBe(true); - expect(loggerMock.error.mock.calls.length === 0).toBe(true); + expect(loggerMock.debug).not.toBeCalled(); + expect(loggerMock.error).not.toBeCalled(); }); test('Returns object with null queryString, if `splitFilters` contains invalid filters or contains filters with no values or invalid values', () => { @@ -55,7 +48,7 @@ describe('validateSplitFilters', () => { groupedFilters: { byName: [], byPrefix: [] } }; expect(validateSplitFilters(loggerMock, splitFilters, STANDALONE_MODE)).toEqual(output); // filters without values - expect(loggerMock.debug.mock.calls[0]).toEqual(["Factory instantiation: splits filtering criteria is 'null'."]); + expect(loggerMock.debug).toBeCalledWith(DEBUG_SPLITS_FILTER, [null]); loggerMock.debug.mockClear(); splitFilters.push( @@ -65,16 +58,16 @@ describe('validateSplitFilters', () => { { type: 'byName', values: [13] }); output.validFilters.push({ type: 'byName', values: [13] }); expect(validateSplitFilters(loggerMock, splitFilters, STANDALONE_MODE)).toEqual(output); // some filters are invalid - expect(loggerMock.debug.mock.calls).toEqual([["Factory instantiation: splits filtering criteria is 'null'."]]); + expect(loggerMock.debug.mock.calls).toEqual([[DEBUG_SPLITS_FILTER, [null]]]); expect(loggerMock.warn.mock.calls).toEqual([ - ["Factory instantiation: split filter at position '3' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."], // invalid value of `type` property - ["Factory instantiation: split filter at position '4' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."], // invalid type of `values` property - ["Factory instantiation: split filter at position '5' is invalid. It must be an object with a valid filter type ('byName' or 'byPrefix') and a list of 'values'."] // invalid type of `type` property + [WARN_SPLITS_FILTER_INVALID, [3]], // invalid value of `type` property + [WARN_SPLITS_FILTER_INVALID, [4]], // invalid type of `values` property + [WARN_SPLITS_FILTER_INVALID, [5]] // invalid type of `type` property ]); expect(loggerMock.error.mock.calls).toEqual([ - ['Factory instantiation: you passed an invalid byName filter value, byName filter value must be a non-empty string.'], - ['Factory instantiation: byName filter must be a non-empty array.'] + [ERROR_INVALID, ['settings', 'byName filter value']], + [ERROR_EMPTY_ARRAY, ['settings', 'byName filter']] ]); }); @@ -89,7 +82,7 @@ describe('validateSplitFilters', () => { groupedFilters: groupedFilters[i] }; expect(validateSplitFilters(loggerMock, splitFilters[i], STANDALONE_MODE)).toEqual(output); // splitFilters #${i} - expect(loggerMock.debug.mock.calls[loggerMock.debug.mock.calls.length - 1]).toEqual([`Factory instantiation: splits filtering criteria is '${queryStrings[i]}'.`]); + expect(loggerMock.debug).lastCalledWith(DEBUG_SPLITS_FILTER, [queryStrings[i]]); } else { // tests where validateSplitFilters throws an exception expect(() => validateSplitFilters(loggerMock, splitFilters[i], STANDALONE_MODE)).toThrow(queryStrings[i]); diff --git a/src/utils/settingsValidation/impressionsMode.ts b/src/utils/settingsValidation/impressionsMode.ts index c81f5460..84ae2f14 100644 --- a/src/utils/settingsValidation/impressionsMode.ts +++ b/src/utils/settingsValidation/impressionsMode.ts @@ -1,4 +1,4 @@ -import { ERROR_38 } from '../../logger/constants'; +import { ERROR_INVALID_IMPRESSIONS_MODE } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { SplitIO } from '../../types'; import { DEBUG, OPTIMIZED } from '../constants'; @@ -6,7 +6,7 @@ import { DEBUG, OPTIMIZED } from '../constants'; export default function validImpressionsMode(log: ILogger, impressionsMode: string): SplitIO.ImpressionsMode { impressionsMode = impressionsMode.toUpperCase(); if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) === -1) { - log.error(ERROR_38, [DEBUG, OPTIMIZED, OPTIMIZED]); + log.error(ERROR_INVALID_IMPRESSIONS_MODE, [[DEBUG, OPTIMIZED], OPTIMIZED]); impressionsMode = OPTIMIZED; } diff --git a/src/utils/settingsValidation/integrations/common.ts b/src/utils/settingsValidation/integrations/common.ts index 61ea19c0..95fa1cd4 100644 --- a/src/utils/settingsValidation/integrations/common.ts +++ b/src/utils/settingsValidation/integrations/common.ts @@ -1,4 +1,4 @@ -import { WARN_21 } from '../../../logger/constants'; +import { WARN_INTEGRATION_INVALID } from '../../../logger/constants'; import { ILogger } from '../../../logger/types'; /** @@ -21,7 +21,7 @@ export function validateIntegrations(settings: { log: ILogger, integrations?: an // Log a warning if at least one item is invalid const invalids = integrations.length - validIntegrations.length; - if (invalids) log.warn(WARN_21, [invalids, invalids === 1 ? 'item' : 'items', invalids === 1 ? 'is' : 'are', extraWarning || '']); + if (invalids) log.warn(WARN_INTEGRATION_INVALID, [invalids, invalids === 1 ? 'item' : 'items', invalids === 1 ? 'is' : 'are', extraWarning || '']); return validIntegrations; } diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index 25e7cf90..8542a44b 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -3,7 +3,7 @@ import { validateSplits } from '../inputValidation/splits'; import { ISplitFiltersValidation } from '../../dtos/types'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { WARN_22, WARN_24, WARN_23, DEBUG_51 } from '../../logger/constants'; +import { WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_EMPTY, WARN_SPLITS_FILTER_INVALID, DEBUG_SPLITS_FILTER, SETTINGS_LB } from '../../logger/constants'; // Split filters metadata. // Ordered according to their precedency when forming the filter query string: `&names=&prefixes=` @@ -39,7 +39,7 @@ function validateFilterType(maybeFilterType: any): maybeFilterType is SplitIO.Sp */ function validateSplitFilter(log: ILogger, type: SplitIO.SplitFilterType, values: string[], maxLength: number) { // validate and remove invalid and duplicated values - let result = validateSplits(log, values, 'Factory instantiation', `${type} filter`, `${type} filter value`); + let result = validateSplits(log, values, SETTINGS_LB, `${type} filter`, `${type} filter value`); if (result) { // check max length @@ -97,12 +97,12 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: if (!maybeSplitFilters) return res; // Warn depending on the mode if (mode !== STANDALONE_MODE) { - log.warn(WARN_22, [STANDALONE_MODE]); + log.warn(WARN_SPLITS_FILTER_IGNORED, [STANDALONE_MODE]); return res; } // Check collection type if (!Array.isArray(maybeSplitFilters) || maybeSplitFilters.length === 0) { - log.warn(WARN_24); + log.warn(WARN_SPLITS_FILTER_EMPTY); return res; } @@ -113,7 +113,7 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: res.groupedFilters[filter.type as SplitIO.SplitFilterType] = res.groupedFilters[filter.type as SplitIO.SplitFilterType].concat(filter.values); return true; } else { - log.warn(WARN_23, [index]); + log.warn(WARN_SPLITS_FILTER_INVALID, [index]); } return false; }); @@ -125,7 +125,7 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: // build query string res.queryString = queryStringBuilder(res.groupedFilters); - log.debug(DEBUG_51, [res.queryString]); + log.debug(DEBUG_SPLITS_FILTER, [res.queryString]); return res; } diff --git a/src/utils/settingsValidation/storage/storageCS.ts b/src/utils/settingsValidation/storage/storageCS.ts index 0c5f4171..d8d1406c 100644 --- a/src/utils/settingsValidation/storage/storageCS.ts +++ b/src/utils/settingsValidation/storage/storageCS.ts @@ -1,7 +1,7 @@ import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS'; import { ISettings } from '../../../types'; import { ILogger } from '../../../logger/types'; -import { WARN_25 } from '../../../logger/constants'; +import { WARN_STORAGE_INVALID } from '../../../logger/constants'; /** * This function validates `settings.storage` object @@ -17,7 +17,7 @@ export function validateStorageCS(settings: { log: ILogger, storage?: any }): IS // @TODO validate its API (Splits cache, MySegments cache, etc) when supporting custom storages if (storage) { if (typeof storage === 'function') return storage; - log.warn(WARN_25); + log.warn(WARN_STORAGE_INVALID); } // return default InMemory storage if provided one is not valid From 8bb385cf8cb057fbfb585f45107c660b800970e6 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 18 Mar 2021 16:33:47 -0300 Subject: [PATCH 40/58] reusing tags in log messages --- src/evaluator/combiners/and.ts | 4 +- src/evaluator/matchers/__tests__/ew.spec.ts | 10 +-- src/evaluator/matchers/__tests__/sw.spec.ts | 10 +-- src/evaluator/value/index.ts | 6 +- src/listeners/__tests__/browser.spec.ts | 4 +- src/listeners/__tests__/node.spec.ts | 2 +- src/logger/constants.ts | 26 ++++-- src/logger/messages/debug.ts | 84 ++++++++++--------- src/logger/messages/debugBrowser.ts | 8 +- src/logger/messages/debugNode.ts | 25 +++--- src/logger/messages/error.ts | 25 +++--- src/logger/messages/errorNode.ts | 7 +- src/logger/messages/info.ts | 45 +++++----- src/logger/messages/warn.ts | 25 +++--- src/logger/messages/warnNode.ts | 4 +- src/sdkClient/sdkClientMethod.ts | 4 +- .../__tests__/SplitsCacheInLocal.spec.ts | 2 +- .../offline/syncTasks/fromObjectSyncTask.ts | 3 +- .../__tests__/preloadedData.spec.ts | 4 +- 19 files changed, 162 insertions(+), 136 deletions(-) diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index b2981f29..7f0dbc95 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -3,7 +3,7 @@ import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { MaybeThenable } from '../../dtos/types'; import { IMatcher } from '../types'; -import { DEBUG_0 } from '../../logger/constants'; +import { DEBUG_ENGINE_COMBINER_AND } from '../../logger/constants'; export default function andCombinerContext(log: ILogger, matchers: IMatcher[]) { @@ -11,7 +11,7 @@ export default function andCombinerContext(log: ILogger, matchers: IMatcher[]) { // Array.prototype.every is supported by target environments const hasMatchedAll = results.every(value => value); - log.debug(DEBUG_0, [hasMatchedAll]); + log.debug(DEBUG_ENGINE_COMBINER_AND, [hasMatchedAll]); return hasMatchedAll; } diff --git a/src/evaluator/matchers/__tests__/ew.spec.ts b/src/evaluator/matchers/__tests__/ew.spec.ts index aeb9eb0a..c5980d0b 100644 --- a/src/evaluator/matchers/__tests__/ew.spec.ts +++ b/src/evaluator/matchers/__tests__/ew.spec.ts @@ -11,11 +11,11 @@ test('MATCHER ENDS_WITH / should return true ONLY when the value ends with ["a", value: ['a', 'b', 'c'] } as IMatcherDto) as IMatcher; - expect(matcher('america')).toBe(true); // america end with ["a", "b", "c"] - expect(matcher('blob')).toBe(true); // blob end with ["a", "b", "c"] - expect(matcher('zodiac')).toBe(true); // zodiac end with ["a", "b", "c"] - expect(matcher('violin')).toBe(false); // t end with ["a", "b", "c"] - expect(matcher('manager')).toBe(false); // t end with ["a", "b", "c"] + expect(matcher('america')).toBe(true); // america ends with ["a", "b", "c"] + expect(matcher('blob')).toBe(true); // blob ends with ["a", "b", "c"] + expect(matcher('zodiac')).toBe(true); // zodiac ends with ["a", "b", "c"] + expect(matcher('violin')).toBe(false); // violin doesn't end with ["a", "b", "c"] + expect(matcher('manager')).toBe(false); // manager doesn't end with ["a", "b", "c"] }); test('MATCHER ENDS_WITH / should return true ONLY when the value ends with ["demo.test.org"]', function () { diff --git a/src/evaluator/matchers/__tests__/sw.spec.ts b/src/evaluator/matchers/__tests__/sw.spec.ts index 312ae8b1..ec8cdb5b 100644 --- a/src/evaluator/matchers/__tests__/sw.spec.ts +++ b/src/evaluator/matchers/__tests__/sw.spec.ts @@ -11,9 +11,9 @@ test('MATCHER STARTS_WITH / should return true ONLY when the value starts with [ value: ['a', 'b', 'c'] } as IMatcherDto) as IMatcher; - expect(matcher('awesome')).toBe(true); // awesome start with ["a", "b", "c"] - expect(matcher('black')).toBe(true); // black start with ["a", "b", "c"] - expect(matcher('chello')).toBe(true); // chello start with ["a", "b", "c"] - expect(matcher('violin')).toBe(false); // t start with ["a", "b", "c"] - expect(matcher('manager')).toBe(false); // t start with ["a", "b", "c"] + expect(matcher('awesome')).toBe(true); // awesome starts with ["a", "b", "c"] + expect(matcher('black')).toBe(true); // black starts with ["a", "b", "c"] + expect(matcher('chello')).toBe(true); // chello starts with ["a", "b", "c"] + expect(matcher('violin')).toBe(false); // violin doesn't start with ["a", "b", "c"] + expect(matcher('manager')).toBe(false); // manager doesn't start with ["a", "b", "c"] }); diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index a7245066..47a928bc 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -2,7 +2,7 @@ import { SplitIO } from '../../types'; import { IMatcherDto } from '../types'; import { ILogger } from '../../logger/types'; import sanitizeValue from './sanitize'; -import { DEBUG_24, WARN_1, WARN_0 } from '../../logger/constants'; +import { DEBUG_24, WARN_ENGINE_NO_ATTRIBUTES, WARN_ENGINE_INVALID_VALUE } from '../../logger/constants'; function parseValue(log: ILogger, key: string, attributeName: string | null, attributes: SplitIO.Attributes) { let value = undefined; @@ -11,7 +11,7 @@ function parseValue(log: ILogger, key: string, attributeName: string | null, att value = attributes[attributeName]; log.debug(DEBUG_24, [attributeName, value]); } else { - log.warn(WARN_1, [attributeName]); + log.warn(WARN_ENGINE_NO_ATTRIBUTES, [attributeName]); } } else { value = key; @@ -31,7 +31,7 @@ export default function value(log: ILogger, key: string, matcherDto: IMatcherDto if (sanitizedValue !== undefined) { return sanitizedValue; } else { - log.warn(WARN_0, [valueToMatch, attributeName ? ' for attribute ' + attributeName : '']); + log.warn(WARN_ENGINE_INVALID_VALUE, [valueToMatch + (attributeName ? ' for attribute ' + attributeName : '')]); return; } } diff --git a/src/listeners/__tests__/browser.spec.ts b/src/listeners/__tests__/browser.spec.ts index cc428917..03a98c79 100644 --- a/src/listeners/__tests__/browser.spec.ts +++ b/src/listeners/__tests__/browser.spec.ts @@ -157,7 +157,7 @@ test('Browser JS listener / Impressions debug mode', (done) => { expect((fakeSplitApi.postTestImpressionsCount as jest.Mock).mock.calls.length).toBe(0); // pre-check and call stop - expect((global.window.removeEventListener as jest.Mock).mock.calls.length === 0).toBe(true); + expect(global.window.removeEventListener).not.toBeCalled(); listener.stop(); // removed correct listener from correct signal on stop. @@ -191,7 +191,7 @@ test('Browser JS listener / Impressions debug mode without sendBeacon API', (don expect((fakeSplitApi.postTestImpressionsCount as jest.Mock).mock.calls.length).toBe(0); // pre-check and call stop - expect((global.window.removeEventListener as jest.Mock).mock.calls.length === 0).toBe(true); + expect(global.window.removeEventListener).not.toBeCalled(); listener.stop(); // removed correct listener from correct signal on stop. diff --git a/src/listeners/__tests__/node.spec.ts b/src/listeners/__tests__/node.spec.ts index cc16aff4..94f6e14c 100644 --- a/src/listeners/__tests__/node.spec.ts +++ b/src/listeners/__tests__/node.spec.ts @@ -17,7 +17,7 @@ test('Node JS listener / Signal Listener class methods and start/stop functional expect(processOnSpy.mock.calls).toEqual([['SIGTERM', listener._sigtermHandler]]); // pre-check and call stop - expect(processRemoveListenerSpy.mock.calls.length === 0).toBe(true); + expect(processRemoveListenerSpy).not.toBeCalled(); listener.stop(); // removed correct listener from correct signal on stop. diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 860c7c18..015c3078 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -1,5 +1,5 @@ // commons -export const DEBUG_0 = 0; +export const DEBUG_ENGINE_COMBINER_AND = 0; export const DEBUG_1 = 1; export const DEBUG_2 = 2; export const DEBUG_3 = 3; @@ -25,8 +25,7 @@ export const DEBUG_22 = 22; export const DEBUG_23 = 23; export const DEBUG_24 = 24; export const DEBUG_25 = 25; -export const DEBUG_31 = 31; -export const DEBUG_32 = 32; // @TODO remove and use DEBUG_31 ('splitio => Retrieving SDK client.') +export const DEBUG_32 = 32; export const DEBUG_33 = 33; export const DEBUG_36 = 36; export const DEBUG_42 = 42; @@ -111,8 +110,8 @@ export const INFO_20 = 120; export const INFO_21 = 121; // commons -export const WARN_0 = 200; -export const WARN_1 = 201; +export const WARN_ENGINE_INVALID_VALUE = 200; +export const WARN_ENGINE_NO_ATTRIBUTES = 201; export const WARN_CLIENT_NO_LISTENER = 202; export const WARN_4 = 204; export const WARN_5 = 205; @@ -140,5 +139,20 @@ export const WARN_API_KEY = 226; // node export const WARN_3 = 203; -// Log tags or categories +// Log tags/categories export const SETTINGS_LB = 'settings'; +export const ENGINE_LB = 'engine'; +export const ENGINE_COMBINER_LB = ENGINE_LB + ':combiner: '; +export const ENGINE_MATCHER_LB = ENGINE_LB + ':matcher: '; +export const ENGINE_VALUE_LB = ENGINE_LB + ':value: '; +export const SYNC_LB = 'sync'; +export const SYNC_OFFLINE_LB = SYNC_LB + ':offline: '; +export const SYNC_STREAMING_LB = SYNC_LB + ':streaming: '; +export const SYNC_SPLITS_LB = SYNC_LB + ':split-changes: '; +export const SYNC_SEGMENTS_LB = SYNC_LB + ':segment-changes: '; +export const SYNC_MYSEGMENTS_LB = SYNC_LB + ':my-segments: '; +export const SYNC_POLLING_LB = SYNC_LB + ':polling: '; +export const SYNC_SUBMITTERS_LB = SYNC_LB + ':submitter: '; +export const IMPRESSIONS_TRACKER_LB = 'impressions-tracker: '; +export const EVENTS_TRACKER_LB = 'events-tracker: '; +export const CLEANUP_LB = 'cleanup: '; diff --git a/src/logger/messages/debug.ts b/src/logger/messages/debug.ts index 91cf7e71..3a067b9b 100644 --- a/src/logger/messages/debug.ts +++ b/src/logger/messages/debug.ts @@ -1,45 +1,47 @@ -import { DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_31, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_SPLITS_FILTER, SETTINGS_LB } from '../constants'; +import { DEBUG_ENGINE_COMBINER_AND, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_SPLITS_FILTER, SETTINGS_LB, ENGINE_LB, ENGINE_COMBINER_LB, ENGINE_MATCHER_LB, ENGINE_VALUE_LB, SYNC_OFFLINE_LB, IMPRESSIONS_TRACKER_LB, SYNC_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB } from '../constants'; export const codesDebug: [number, string][] = [ - [DEBUG_0, 'splitio-engine:combiner => [andCombiner] evaluates to %s'], - [DEBUG_1, 'splitio-engine:combiner => Treatment found: %s'], - [DEBUG_2, 'splitio-engine:combiner => All predicates evaluated, no treatment found.'], - [DEBUG_3, 'splitio-engine => [engine] using algo "murmur" bucket %s for key %s using seed %s - treatment %s'], - [DEBUG_4, 'splitio-engine:matcher => [allMatcher] is always true'], - [DEBUG_5, 'splitio-engine:matcher => [betweenMatcher] is %s between %s and %s? %s'], - [DEBUG_6, 'splitio-engine:matcher => [booleanMatcher] %s === %s'], - [DEBUG_7, 'splitio-engine:matcher => [containsAllMatcher] %s contains all elements of %s? %s'], - [DEBUG_8, 'splitio-engine:matcher => [containsAnyMatcher] %s contains at least an element of %s? %s'], - [DEBUG_9, 'splitio-engine:matcher => [containsStringMatcher] %s contains %s? %s'], - [DEBUG_10, 'splitio-engine:matcher => [dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], - [DEBUG_11, 'splitio-engine:matcher => [dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], - [DEBUG_12, 'splitio-engine:matcher => [equalToMatcher] is %s equal to %s? %s'], - [DEBUG_13, 'splitio-engine:matcher => [equalToSetMatcher] is %s equal to set %s? %s'], - [DEBUG_14, 'splitio-engine:matcher => [endsWithMatcher] %s ends with %s? %s'], - [DEBUG_15, 'splitio-engine:matcher => [greaterThanEqualMatcher] is %s greater than %s? %s'], - [DEBUG_16, 'splitio-engine:matcher => [lessThanEqualMatcher] is %s less than %s? %s'], - [DEBUG_17, 'splitio-engine:matcher => [partOfMatcher] %s is part of %s? %s'], - [DEBUG_18, 'splitio-engine:matcher => [asyncSegmentMatcher] evaluated %s / %s => %s'], - [DEBUG_19, 'splitio-engine:matcher => [segmentMatcher] evaluated %s / %s => %s'], - [DEBUG_20, 'splitio-engine:matcher => [stringMatcher] does %s matches with %s? %s'], - [DEBUG_21, 'splitio-engine:matcher => [stringMatcher] %s is an invalid regex'], - [DEBUG_22, 'splitio-engine:matcher => [startsWithMatcher] %s starts with %s? %s'], - [DEBUG_23, 'splitio-engine:matcher => [whitelistMatcher] evaluated %s in [%s] => %s'], - [DEBUG_24, 'splitio-engine:value => Extracted attribute [%s], [%s] will be used for matching.'], - [DEBUG_25, 'splitio-engine:sanitize => Attempted to sanitize [%s] which should be of type [%s]. \n Sanitized and processed value => [%s]'], - [DEBUG_31, 'splitio => Retrieving SDK client.'], - [DEBUG_32, 'splitio => Retrieving default SDK client.'], // @TODO remove and use 'splitio => Retrieving SDK client.' - [DEBUG_33, 'splitio => Retrieving existing SDK client.'], - [DEBUG_36, 'splitio-producer:offline => Splits data: '], - [DEBUG_42, 'splitio-sync:split-changes => Spin up split update using since = %s'], - [DEBUG_43, 'splitio-sync:split-changes => New splits %s'], - [DEBUG_44, 'splitio-sync:split-changes => Removed splits %s'], - [DEBUG_45, 'splitio-sync:split-changes => Segment names collected %s'], - [DEBUG_46, 'splitio-sync:sse-handler => New SSE message received, with data: %s.'], - [DEBUG_47, 'splitio-sync:task => Starting %s. Running each %s millis'], - [DEBUG_48, 'splitio-sync:task => Running %s'], - [DEBUG_49, 'splitio-sync:task => Stopping %s'], - [DEBUG_50, 'splitio-client:impressions-tracker => Successfully stored %s impression%s.'], + // evaluator + [DEBUG_ENGINE_COMBINER_AND, ENGINE_COMBINER_LB + '[andCombiner] evaluates to %s'], + [DEBUG_1, ENGINE_COMBINER_LB + 'Treatment found: %s'], + [DEBUG_2, ENGINE_COMBINER_LB + 'All predicates evaluated, no treatment found.'], + [DEBUG_3, ENGINE_LB + ': using algo "murmur" bucket %s for key %s using seed %s - treatment %s'], + [DEBUG_4, ENGINE_MATCHER_LB + '[allMatcher] is always true'], + [DEBUG_5, ENGINE_MATCHER_LB + '[betweenMatcher] is %s between %s and %s? %s'], + [DEBUG_6, ENGINE_MATCHER_LB + '[booleanMatcher] %s === %s'], + [DEBUG_7, ENGINE_MATCHER_LB + '[containsAllMatcher] %s contains all elements of %s? %s'], + [DEBUG_8, ENGINE_MATCHER_LB + '[containsAnyMatcher] %s contains at least an element of %s? %s'], + [DEBUG_9, ENGINE_MATCHER_LB + '[containsStringMatcher] %s contains %s? %s'], + [DEBUG_10, ENGINE_MATCHER_LB + '[dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], + [DEBUG_11, ENGINE_MATCHER_LB + '[dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], + [DEBUG_12, ENGINE_MATCHER_LB + '[equalToMatcher] is %s equal to %s? %s'], + [DEBUG_13, ENGINE_MATCHER_LB + '[equalToSetMatcher] is %s equal to set %s? %s'], + [DEBUG_14, ENGINE_MATCHER_LB + '[endsWithMatcher] %s ends with %s? %s'], + [DEBUG_15, ENGINE_MATCHER_LB + '[greaterThanEqualMatcher] is %s greater than %s? %s'], + [DEBUG_16, ENGINE_MATCHER_LB + '[lessThanEqualMatcher] is %s less than %s? %s'], + [DEBUG_17, ENGINE_MATCHER_LB + '[partOfMatcher] %s is part of %s? %s'], + [DEBUG_18, ENGINE_MATCHER_LB + '[asyncSegmentMatcher] evaluated %s / %s => %s'], + [DEBUG_19, ENGINE_MATCHER_LB + '[segmentMatcher] evaluated %s / %s => %s'], + [DEBUG_20, ENGINE_MATCHER_LB + '[stringMatcher] does %s matches with %s? %s'], + [DEBUG_21, ENGINE_MATCHER_LB + '[stringMatcher] %s is an invalid regex'], + [DEBUG_22, ENGINE_MATCHER_LB + '[startsWithMatcher] %s starts with %s? %s'], + [DEBUG_23, ENGINE_MATCHER_LB + '[whitelistMatcher] evaluated %s in [%s] => %s'], + [DEBUG_24, ENGINE_VALUE_LB + 'Extracted attribute [%s], [%s] will be used for matching.'], + [DEBUG_25, ENGINE_LB + ':sanitize: Attempted to sanitize [%s] which should be of type [%s]. Sanitized and processed value => [%s]'], + // SDK + [DEBUG_32, ' Retrieving default SDK client.'], + [DEBUG_33, ' Retrieving existing SDK client.'], + // synchronizer + [DEBUG_36, SYNC_OFFLINE_LB + 'Splits data: \n%s'], + [DEBUG_42, SYNC_SPLITS_LB + 'Spin up split update using since = %s'], + [DEBUG_43, SYNC_SPLITS_LB + 'New splits %s'], + [DEBUG_44, SYNC_SPLITS_LB + 'Removed splits %s'], + [DEBUG_45, SYNC_SPLITS_LB + 'Segment names collected %s'], + [DEBUG_46, SYNC_STREAMING_LB + 'New SSE message received, with data: %s.'], + [DEBUG_47, SYNC_LB + ': Starting %s. Running each %s millis'], + [DEBUG_48, SYNC_LB + ': Running %s'], + [DEBUG_49, SYNC_LB + ': Stopping %s'], + [DEBUG_50, IMPRESSIONS_TRACKER_LB + 'Successfully stored %s impression%s.'], // initialization / settings validation - [DEBUG_SPLITS_FILTER, SETTINGS_LB+': splits filtering criteria is "%s".'] + [DEBUG_SPLITS_FILTER, SETTINGS_LB + ': splits filtering criteria is "%s".'] ]; diff --git a/src/logger/messages/debugBrowser.ts b/src/logger/messages/debugBrowser.ts index 86732fcf..df641ca9 100644 --- a/src/logger/messages/debugBrowser.ts +++ b/src/logger/messages/debugBrowser.ts @@ -1,6 +1,8 @@ -import { DEBUG_26, DEBUG_27 } from '../constants'; +import { CLEANUP_LB, DEBUG_26, DEBUG_27 } from '../constants'; + +const HANDLER_LB = ' flush handler when unload page event is triggered.'; export const codesDebugBrowser: [number, string][] = [ - [DEBUG_26, 'splitio-client:cleanup => Registering flush handler when unload page event is triggered.'], - [DEBUG_27, 'splitio-client:cleanup => Deregistering flush handler when unload page event is triggered.'], + [DEBUG_26, CLEANUP_LB + 'Registering' + HANDLER_LB], + [DEBUG_27, CLEANUP_LB + 'Deregistering' + HANDLER_LB], ]; diff --git a/src/logger/messages/debugNode.ts b/src/logger/messages/debugNode.ts index 9bb08f6b..0138a56e 100644 --- a/src/logger/messages/debugNode.ts +++ b/src/logger/messages/debugNode.ts @@ -1,14 +1,17 @@ -import { DEBUG_28, DEBUG_29, DEBUG_30, DEBUG_39, DEBUG_40, DEBUG_41, DEBUG_34, DEBUG_35, DEBUG_37, DEBUG_38 } from '../constants'; +import { DEBUG_28, DEBUG_29, DEBUG_30, DEBUG_39, DEBUG_40, DEBUG_41, DEBUG_34, DEBUG_35, DEBUG_37, DEBUG_38, CLEANUP_LB, SYNC_OFFLINE_LB, SYNC_POLLING_LB, SYNC_SEGMENTS_LB } from '../constants'; + +const HANDLER_LB = ' cleanup handlers.'; export const codesDebugNode: [number, string][] = [ - [DEBUG_28, 'splitio-client:cleanup => Registering cleanup handlers.'], - [DEBUG_29, 'splitio-client:cleanup => Deregistering cleanup handlers.'], - [DEBUG_30, 'splitio-client:cleanup => Split SDK graceful shutdown after SIGTERM.'], - [DEBUG_39, 'splitio-sync:segment-changes => Processed %s with till = %s. Added: %s. Removed: %s'], - [DEBUG_40, 'splitio-sync:segment-changes => Processing segment %s'], - [DEBUG_41, 'splitio-sync:segment-changes => Started segments update'], - [DEBUG_34, 'splitio-offline:splits-fetcher => Ignoring empty line or comment at #%s'], - [DEBUG_35, 'splitio-offline:splits-fetcher => Ignoring line since it does not have exactly two columns #%s'], - [DEBUG_37, 'splitio-sync:polling-manager => Splits will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? - [DEBUG_38, 'splitio-sync:polling-manager => Segments will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? + [DEBUG_28, CLEANUP_LB + 'Registering' + HANDLER_LB], + [DEBUG_29, CLEANUP_LB + 'Deregistering' + HANDLER_LB], + [DEBUG_30, CLEANUP_LB + 'Split SDK graceful shutdown after SIGTERM.'], + // synchronizer + [DEBUG_39, SYNC_SEGMENTS_LB + 'Processed %s with till = %s. Added: %s. Removed: %s'], + [DEBUG_40, SYNC_SEGMENTS_LB + 'Processing segment %s'], + [DEBUG_41, SYNC_SEGMENTS_LB + 'Started segments update'], + [DEBUG_34, SYNC_OFFLINE_LB + 'Ignoring empty line or comment at #%s'], + [DEBUG_35, SYNC_OFFLINE_LB + 'Ignoring line since it does not have exactly two columns #%s'], + [DEBUG_37, SYNC_POLLING_LB + 'Splits will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? + [DEBUG_38, SYNC_POLLING_LB + 'Segments will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? ]; diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index f48bd7ab..931bc1f1 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -1,16 +1,19 @@ -import { ERROR_0, ERROR_2, ERROR_CLIENT_LISTENER, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_CLIENT_DESTROYED, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_IMPRESSIONS_MODE, ERROR_39, SETTINGS_LB } from '../constants'; +import { ERROR_0, ERROR_2, ERROR_CLIENT_LISTENER, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_CLIENT_DESTROYED, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_IMPRESSIONS_MODE, ERROR_39, SETTINGS_LB, ENGINE_COMBINER_LB, SYNC_OFFLINE_LB, SYNC_STREAMING_LB, IMPRESSIONS_TRACKER_LB } from '../constants'; export const codesError: [number, string][] = [ - [ERROR_0, 'splitio-engine:combiner => Invalid Split provided, no valid conditions found'], - [ERROR_2, 'splitio-utils:logger => Invalid Log Level - No changes to the logs will be applied.'], - [ERROR_4, 'splitio => Manager instance is not available. Provide the manager module on settings.'], - [ERROR_5, 'splitio-services:service => %s The SDK will not get ready.'], - [ERROR_7, 'splitio-producer:offline => There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], - [ERROR_9, 'splitio-sync:sse-handler => Fail to connect to streaming, with error message: %s'], - [ERROR_10, 'splitio-sync:push-manager => Failed to authenticate for streaming. Error: "%s".'], - [ERROR_11, 'splitio-client:impressions-tracker => Could not store impressions bulk with %s impression%s. Error: %s'], - [ERROR_12, 'splitio-client:impressions-tracker => Impression listener logImpression method threw: %s.'], - [ERROR_39, 'splitio-services:service => Response status is not OK. Status: %s. URL: %s. Message: %s'], + // evaluator + [ERROR_0, ENGINE_COMBINER_LB + 'Invalid Split provided, no valid conditions found'], + // SDK + [ERROR_2, 'logger: Invalid Log Level - No changes to the logs will be applied.'], + [ERROR_4, ' Manager instance is not available.'], + [ERROR_5, ' The SDK will not get ready. Reason: %s'], + // synchronizer + [ERROR_7, SYNC_OFFLINE_LB + 'There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], + [ERROR_9, SYNC_STREAMING_LB + 'Fail to connect to streaming, with error message: %s'], + [ERROR_10, SYNC_STREAMING_LB + 'Failed to authenticate for streaming. Error: "%s".'], + [ERROR_11, IMPRESSIONS_TRACKER_LB + 'Could not store impressions bulk with %s impression%s. Error: %s'], + [ERROR_12, IMPRESSIONS_TRACKER_LB + 'Impression listener logImpression method threw: %s.'], + [ERROR_39, ' Response status is not OK. Status: %s. URL: %s. Message: %s'], // client status [ERROR_CLIENT_LISTENER, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], [ERROR_CLIENT_DESTROYED, '%s: Client has already been destroyed - no calls possible.'], diff --git a/src/logger/messages/errorNode.ts b/src/logger/messages/errorNode.ts index 54091cca..ff75d031 100644 --- a/src/logger/messages/errorNode.ts +++ b/src/logger/messages/errorNode.ts @@ -1,8 +1,7 @@ -import { ERROR_1, ERROR_API_KEY_INVALID, ERROR_6, SETTINGS_LB } from '../constants'; +import { ERROR_1, ERROR_API_KEY_INVALID, ERROR_6, SETTINGS_LB, CLEANUP_LB, SYNC_OFFLINE_LB } from '../constants'; export const codesErrorNode: [number, string][] = [ - [ERROR_1, 'splitio-client:cleanup => Error with Split graceful shutdown: %s'], - [ERROR_6, 'splitio-offline:splits-fetcher => Ignoring entry on YAML since the format is incorrect.'], - // initialization / settings validation + [ERROR_1, CLEANUP_LB + 'Error with Split graceful shutdown: %s'], + [ERROR_6, SYNC_OFFLINE_LB + 'Ignoring entry on YAML since the format is incorrect.'], [ERROR_API_KEY_INVALID, SETTINGS_LB+': you passed a Client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.'], ]; diff --git a/src/logger/messages/info.ts b/src/logger/messages/info.ts index ddb05a58..5cb751a1 100644 --- a/src/logger/messages/info.ts +++ b/src/logger/messages/info.ts @@ -1,4 +1,4 @@ -import { INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21 } from '../constants'; +import { INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21, EVENTS_TRACKER_LB, SYNC_POLLING_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, SYNC_SUBMITTERS_LB, IMPRESSIONS_TRACKER_LB } from '../constants'; const READY_MSG = 'Split SDK is ready'; @@ -6,25 +6,26 @@ export const codesInfo: [number, string][] = [ // client status [INFO_CLIENT_READY_FROM_CACHE, READY_MSG + ' from cache'], [INFO_CLIENT_READY, READY_MSG], - - [INFO_2, 'splitio-client => Split: %s. Key: %s. Evaluation: %s. Label: %s'], - [INFO_3, 'splitio-client => Queueing corresponding impression.'], - [INFO_4, 'splitio => New shared client instance created.'], - [INFO_5, 'splitio => New Split SDK instance created.'], - [INFO_6, 'splitio => Manager instance retrieved.'], - [INFO_7, 'splitio-sync:polling-manager => Turning segments data polling %s.'], - [INFO_8, 'splitio-sync:polling-manager => Starting polling'], - [INFO_9, 'splitio-sync:polling-manager => Stopping polling'], - [INFO_10, 'splitio-sync:split-changes => Retrying download of splits #%s. Reason: %s'], - [INFO_11, 'splitio-sync:push-manager => Refreshing streaming token in %s seconds.'], - [INFO_12, 'splitio-sync:push-manager => Attempting to reconnect in %s seconds.'], - [INFO_13, 'splitio-sync:push-manager => Connecting to push streaming.'], - [INFO_14, 'splitio-sync:push-manager => Streaming is not available. Switching to polling mode.'], - [INFO_15, 'splitio-sync:push-manager => Disconnecting from push streaming.'], - [INFO_16, 'splitio-sync:submitters => Flushing full events queue and reseting timer.'], - [INFO_17, 'splitio-sync:submitters => Pushing %s %s.'], - [INFO_18, 'splitio-sync:sync-manager => Streaming not available. Starting periodic fetch of data.'], - [INFO_19, 'splitio-sync:sync-manager => Streaming couldn\'t connect. Continue periodic fetch of data.'], - [INFO_20, 'splitio-sync:sync-manager => PUSH (re)connected. Syncing and stopping periodic fetch of data.'], - [INFO_21, 'splitio-client:event-tracker => Successfully qeued %s'] + // SDK + [INFO_2, IMPRESSIONS_TRACKER_LB +'Split: %s. Key: %s. Evaluation: %s. Label: %s'], + [INFO_3, IMPRESSIONS_TRACKER_LB +'Queueing corresponding impression.'], + [INFO_4, ' New shared client instance created.'], + [INFO_5, ' New Split SDK instance created.'], + [INFO_6, ' Manager instance retrieved.'], + // synchronizer + [INFO_7, SYNC_POLLING_LB + 'Turning segments data polling %s.'], + [INFO_8, SYNC_POLLING_LB + 'Starting polling'], + [INFO_9, SYNC_POLLING_LB + 'Stopping polling'], + [INFO_10, SYNC_SPLITS_LB + 'Retrying download of splits #%s. Reason: %s'], + [INFO_16, SYNC_SUBMITTERS_LB + 'Flushing full events queue and reseting timer.'], + [INFO_17, SYNC_SUBMITTERS_LB + 'Pushing %s %s.'], + [INFO_11, SYNC_STREAMING_LB + 'Refreshing streaming token in %s seconds.'], + [INFO_12, SYNC_STREAMING_LB + 'Attempting to reconnect in %s seconds.'], + [INFO_13, SYNC_STREAMING_LB + 'Connecting to streaming.'], + [INFO_14, SYNC_STREAMING_LB + 'Streaming is disabled for given Api key. Switching to polling mode.'], + [INFO_15, SYNC_STREAMING_LB + 'Disconnecting from streaming.'], + [INFO_18, SYNC_STREAMING_LB + 'Streaming not available. Starting polling.'], + [INFO_19, SYNC_STREAMING_LB + 'Streaming couldn\'t connect. Continue polling.'], + [INFO_20, SYNC_STREAMING_LB + 'Streaming (re)connected. Syncing and stopping polling.'], + [INFO_21, EVENTS_TRACKER_LB + 'Successfully qeued %s'] ]; diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index e24b021a..f351cd2d 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -1,16 +1,19 @@ -import { WARN_0, WARN_1, WARN_CLIENT_NO_LISTENER, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, WARN_CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, SETTINGS_LB } from '../constants'; +import { WARN_ENGINE_INVALID_VALUE, WARN_ENGINE_NO_ATTRIBUTES, WARN_CLIENT_NO_LISTENER, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, WARN_CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, SETTINGS_LB, ENGINE_VALUE_LB, EVENTS_TRACKER_LB, SYNC_MYSEGMENTS_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, SYNC_SUBMITTERS_LB } from '../constants'; export const codesWarn: [number, string][] = [ - [WARN_0, 'splitio-engine:value => Value %s %sdoesn\'t match with expected type.'], - [WARN_1, 'splitio-engine:value => Defined attribute [%s], no attributes received.'], - [WARN_4, 'splitio-sync:my-segments => Retrying download of segments #%s. Reason: %s'], - [WARN_5, 'splitio-sync:split-changes => Error while doing fetch of Splits. %s'], - [WARN_6, 'splitio-sync:sse-handler => Error parsing SSE error notification: %s'], - [WARN_7, 'splitio-sync:sse-handler => Error parsing new SSE message notification: %s'], - [WARN_8, 'splitio-sync:push-manager => %sFalling back to polling mode.'], - [WARN_9, 'splitio-sync:submitters => Droping %s %s after retry. Reason %s.'], - [WARN_10, 'splitio-sync:submitters => Failed to push %s %s, keeping data to retry on next iteration. Reason %s.'], - [WARN_11, 'splitio-client:event-tracker => Failed to queue %s'], + // evaluator + [WARN_ENGINE_INVALID_VALUE, ENGINE_VALUE_LB + 'Value %s doesn\'t match with expected type.'], + [WARN_ENGINE_NO_ATTRIBUTES, ENGINE_VALUE_LB + 'Defined attribute [%s], no attributes received.'], + // synchronizer + [WARN_4, SYNC_MYSEGMENTS_LB + 'Retrying download of segments #%s. Reason: %s'], + [WARN_5, SYNC_SPLITS_LB + 'Error while doing fetch of Splits. %s'], + [WARN_6, SYNC_STREAMING_LB + 'Error parsing SSE error notification: %s'], + [WARN_7, SYNC_STREAMING_LB + 'Error parsing new SSE message notification: %s'], + [WARN_8, SYNC_STREAMING_LB + 'Falling back to polling mode. Reason: %s'], + [WARN_9, SYNC_SUBMITTERS_LB + 'Droping %s %s after retry. Reason: %s.'], + [WARN_10, SYNC_SUBMITTERS_LB + 'Failed to push %s %s, keeping data to retry on next iteration. Reason: %s.'], + // SDK + [WARN_11, EVENTS_TRACKER_LB + 'Failed to queue %s'], // client status [WARN_CLIENT_NOT_READY, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], [WARN_CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], diff --git a/src/logger/messages/warnNode.ts b/src/logger/messages/warnNode.ts index 12d1724f..1a5692b8 100644 --- a/src/logger/messages/warnNode.ts +++ b/src/logger/messages/warnNode.ts @@ -1,5 +1,5 @@ -import { WARN_3 } from '../constants'; +import { SYNC_OFFLINE_LB, WARN_3 } from '../constants'; export const codesWarnNode: [number, string][] = [ - [WARN_3, 'splitio-offline:splits-fetcher => .split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'], + [WARN_3, SYNC_OFFLINE_LB + '.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'], ]; diff --git a/src/sdkClient/sdkClientMethod.ts b/src/sdkClient/sdkClientMethod.ts index f9615650..9498d0f0 100644 --- a/src/sdkClient/sdkClientMethod.ts +++ b/src/sdkClient/sdkClientMethod.ts @@ -1,7 +1,7 @@ import { ISdkClientFactoryParams } from './types'; import { SplitIO } from '../types'; import { sdkClientFactory } from './sdkClient'; -import { DEBUG_31 } from '../logger/constants'; +import { DEBUG_32 } from '../logger/constants'; /** * Factory of client method for server-side SDKs (ISDK and IAsyncSDK) @@ -15,7 +15,7 @@ export function sdkClientMethodFactory(params: ISdkClientFactoryParams): () => S throw new Error('Shared Client not supported by the storage mechanism. Create isolated instances instead.'); } - log.debug(DEBUG_31); + log.debug(DEBUG_32); return clientInstance; }; } diff --git a/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts b/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts index 65bc828b..4430afe7 100644 --- a/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts +++ b/src/storages/inLocalStorage/__tests__/SplitsCacheInLocal.spec.ts @@ -118,7 +118,7 @@ test('SPLIT CACHE / LocalStorage / killLocally', () => { let updated = cache.killLocally('nonexistent_split', 'other_treatment', 101); const nonexistentSplit = cache.getSplit('nonexistent_split'); - expect(updated).toBe(false); // t exist + expect(updated).toBe(false); // killLocally resolves without update if split doesn't exist expect(nonexistentSplit).toBe(null); // non-existent split keeps being non-existent // kill an existent split diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index 0ffb2f5a..a3ad3273 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -34,8 +34,7 @@ export function fromObjectUpdaterFactory( } if (!loadError && splitsMock) { - log.debug(DEBUG_36); - log.debug(JSON.stringify(splitsMock)); + log.debug(DEBUG_36, [JSON.stringify(splitsMock)]); forOwn(splitsMock, function (val, name) { splits.push([ diff --git a/src/utils/inputValidation/__tests__/preloadedData.spec.ts b/src/utils/inputValidation/__tests__/preloadedData.spec.ts index 248aaf12..381cba4a 100644 --- a/src/utils/inputValidation/__tests__/preloadedData.spec.ts +++ b/src/utils/inputValidation/__tests__/preloadedData.spec.ts @@ -144,14 +144,14 @@ test('INPUT VALIDATION for preloadedData', () => { expect(loggerMock.error.mock.calls[0]).toEqual([testCase.error]); // Should log the error for the invalid preloadedData. loggerMock.error.mockClear(); } else { - expect(loggerMock.error.mock.calls.length === 0).toBe(true); // Should not log any error. + expect(loggerMock.error).not.toBeCalled(); // Should not log any error. } if (testCase.warn) { expect(loggerMock.warn.mock.calls[0]).toEqual([testCase.warn]); // Should log the warning for the given preloadedData. loggerMock.warn.mockClear(); } else { - expect(loggerMock.warn.mock.calls.length === 0).toBe(true); // Should not log any warning. + expect(loggerMock.warn).not.toBeCalled(); // Should not log any warning. } } }); From 6aaf046c2aacce27d6f3b434d9b671ac96327094 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 18 Mar 2021 18:06:35 -0300 Subject: [PATCH 41/58] added log prefix to remaining logs --- src/integrations/ga/GaToSplit.ts | 20 ++++++++--------- src/integrations/ga/SplitToGa.ts | 13 +++++------ .../ga/__tests__/SplitToGa.spec.ts | 8 +++---- src/logger/sdkLogger.ts | 2 -- .../inLocalStorage/MySegmentsCacheInLocal.ts | 9 ++++---- .../inLocalStorage/SplitsCacheInLocal.ts | 21 +++++++++--------- src/storages/inLocalStorage/index.ts | 6 ++--- src/storages/inRedis/EventsCacheInRedis.ts | 6 ++--- src/storages/inRedis/RedisAdapter.ts | 22 +++++++++---------- src/storages/inRedis/SplitsCacheInRedis.ts | 14 ++++++------ 10 files changed, 58 insertions(+), 63 deletions(-) diff --git a/src/integrations/ga/GaToSplit.ts b/src/integrations/ga/GaToSplit.ts index 10bfd135..befa31f1 100644 --- a/src/integrations/ga/GaToSplit.ts +++ b/src/integrations/ga/GaToSplit.ts @@ -12,9 +12,9 @@ import { SplitIO } from '../../types'; import { Identity, GoogleAnalyticsToSplitOptions } from './types'; import { ILogger } from '../../logger/types'; import { IIntegrationFactoryParams } from '../types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-ga-to-split'); -const logNameMapper = 'splitio-ga-to-split:mapper'; + +const logPrefix = 'ga-to-split: '; +const logNameMapper = 'ga-to-split:mapper'; /** * Provides a plugin to use with analytics.js, accounting for the possibility @@ -169,7 +169,7 @@ export function fixEventTypeId(log: ILogger, eventTypeId: any) { .replace(INVALID_PREFIX_REGEX, '') .replace(INVALID_SUBSTRING_REGEX, '_'); const truncated = fixed.slice(0, 80); - if (truncated.length < fixed.length) log.warn('EventTypeId was truncated because it cannot be more than 80 characters long.'); + if (truncated.length < fixed.length) log.warn(logPrefix + 'EventTypeId was truncated because it cannot be more than 80 characters long.'); return truncated; } @@ -210,19 +210,19 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par const validIdentities = validateIdentities(opts.identities); if (validIdentities.length === 0) { - log.warn('No valid identities were provided. Please check that you are passing a valid list of identities or providing a traffic type at the SDK configuration.'); + log.warn(logPrefix + 'No valid identities were provided. Please check that you are passing a valid list of identities or providing a traffic type at the SDK configuration.'); return; } const invalids = validIdentities.length - opts.identities.length; if (invalids) { - log.warn(`${invalids} identities were discarded because they are invalid or duplicated. Identities must be an array of objects with key and trafficType.`); + log.warn(logPrefix + `${invalids} identities were discarded because they are invalid or duplicated. Identities must be an array of objects with key and trafficType.`); } opts.identities = validIdentities; // Validate prefix if (!isString(opts.prefix)) { - log.warn('The provided `prefix` was ignored since it is invalid. Please check that you are passing a string object as `prefix`.'); + log.warn(logPrefix + 'The provided `prefix` was ignored since it is invalid. Please check that you are passing a string object as `prefix`.'); opts.prefix = undefined; } @@ -239,7 +239,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par try { if (opts.filter && !opts.filter(model)) return; } catch (err) { - log.warn(`GaToSplit custom filter threw: ${err}`); + log.warn(logPrefix + `custom filter threw: ${err}`); return; } @@ -249,7 +249,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par try { eventData = opts.mapper(model, eventData as SplitIO.EventData); } catch (err) { - log.warn(`GaToSplit custom mapper threw: ${err}`); + log.warn(logPrefix + `custom mapper threw: ${err}`); return; } if (!eventData) @@ -278,7 +278,7 @@ export default function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, par } }); - log.info('Started GA-to-Split integration'); + log.info(logPrefix + 'integration started'); } } diff --git a/src/integrations/ga/SplitToGa.ts b/src/integrations/ga/SplitToGa.ts index 0ac29ceb..df933c21 100644 --- a/src/integrations/ga/SplitToGa.ts +++ b/src/integrations/ga/SplitToGa.ts @@ -5,9 +5,8 @@ import { SplitIO } from '../../types'; import { IIntegration } from '../types'; import { SplitToGoogleAnalyticsOptions } from './types'; import { ILogger } from '../../logger/types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-split-to-ga'); +const logPrefix = 'split-to-ga: '; const noGaWarning = '`ga` command queue not found.'; const noHit = 'No hit was sent.'; @@ -64,7 +63,7 @@ export default class SplitToGa implements IIntegration { static validateFieldsObject(log: ILogger, fieldsObject: any): fieldsObject is UniversalAnalytics.FieldsObject { if (fieldsObject && fieldsObject.hitType) return true; - log.warn('your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.'); + log.warn(logPrefix + 'your custom mapper returned an invalid FieldsObject instance. It must be an object with at least a `hitType` field.'); return false; } @@ -90,8 +89,8 @@ export default class SplitToGa implements IIntegration { this.events = options.events; } - log.info('Started Split-to-GA integration'); - if (typeof SplitToGa.getGa() !== 'function') log.warn(`${noGaWarning} No hits will be sent until it is available.`); + log.info(logPrefix + 'integration started'); + if (typeof SplitToGa.getGa() !== 'function') log.warn(logPrefix + `${noGaWarning} No hits will be sent until it is available.`); } queue(data: SplitIO.IntegrationData) { @@ -116,7 +115,7 @@ export default class SplitToGa implements IIntegration { if (!fieldsObject || !SplitToGa.validateFieldsObject(this.log, fieldsObject)) return; } } catch (err) { - this.log.warn(`SplitToGa queue method threw: ${err}. ${noHit}`); + this.log.warn(logPrefix + `queue method threw: ${err}. ${noHit}`); return; } @@ -129,7 +128,7 @@ export default class SplitToGa implements IIntegration { ga(sendCommand, fieldsObject); }); } else { - this.log.warn(`${noGaWarning} ${noHit}`); + this.log.warn(logPrefix + `${noGaWarning} ${noHit}`); } } diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index 04b0ccdf..2f486e8f 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -138,7 +138,7 @@ describe('SplitToGa', () => { }) as SplitToGa; ga.mockClear(); instance2.queue(fakeImpression); - expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` if a Split data (impression or event) is filtered + expect(ga).not.toBeCalled(); // shouldn't queue `ga send` if a Split data (impression or event) is filtered instance2.queue(fakeEvent); expect(ga.mock.calls).toEqual([ @@ -171,7 +171,7 @@ describe('SplitToGa', () => { }) as SplitToGa; ga.mockClear(); instance4.queue(fakeImpression); - expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` if a custom mapper throw an exception + expect(ga).not.toBeCalled(); // shouldn't queue `ga send` if a custom mapper throw an exception // `impressions` flags const instance5 = new SplitToGa(loggerMock, { @@ -179,7 +179,7 @@ describe('SplitToGa', () => { }) as SplitToGa; ga.mockClear(); instance5.queue(fakeImpression); - expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` for an impression if `impressions` flag is false + expect(ga).not.toBeCalled(); // shouldn't queue `ga send` for an impression if `impressions` flag is false // `impressions` flags const instance6 = new SplitToGa(loggerMock, { @@ -187,7 +187,7 @@ describe('SplitToGa', () => { }) as SplitToGa; ga.mockClear(); instance6.queue(fakeEvent); - expect(ga.mock.calls.length === 0).toBe(true); // t queue `ga send` for a event if `events` flag is false + expect(ga).not.toBeCalled(); // shouldn't queue `ga send` for a event if `events` flag is false // test teardown gaRemove(); diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 94c8b5fa..32840ea5 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -2,8 +2,6 @@ import { LogLevels, isLogLevelString } from './index'; import { ILoggerAPI } from '../types'; import { ILogger } from './types'; import { ERROR_2 } from './constants'; -// const log = logFactory('splitio-utils:logger'); - /** * The public Logger utility API exposed via SplitFactory, used to update the log level. diff --git a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts index f731821b..cfa58b9f 100644 --- a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +++ b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts @@ -1,8 +1,7 @@ import { ILogger } from '../../logger/types'; import AbstractSegmentsCacheSync from '../AbstractSegmentsCacheSync'; import KeyBuilderCS from '../KeyBuilderCS'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-storage:localstorage'); +import { logPrefix } from './index'; const DEFINED = '1'; @@ -23,7 +22,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { * @NOTE this method is not being used at the moment. */ clear() { - this.log.info('Flushing MySegments data from localStorage'); + this.log.info(logPrefix + 'Flushing MySegments data from localStorage'); // We cannot simply call `localStorage.clear()` since that implies removing user items from the storage // We could optimize next sentence, since it implies iterating over all localStorage items @@ -37,7 +36,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { localStorage.setItem(segmentKey, DEFINED); return true; } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); return false; } } @@ -49,7 +48,7 @@ export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { localStorage.removeItem(segmentKey); return true; } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); return false; } } diff --git a/src/storages/inLocalStorage/SplitsCacheInLocal.ts b/src/storages/inLocalStorage/SplitsCacheInLocal.ts index b84aec44..47ec5584 100644 --- a/src/storages/inLocalStorage/SplitsCacheInLocal.ts +++ b/src/storages/inLocalStorage/SplitsCacheInLocal.ts @@ -3,8 +3,7 @@ import AbstractSplitsCacheSync, { usesSegments } from '../AbstractSplitsCacheSyn import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang'; import KeyBuilderCS from '../KeyBuilderCS'; import { ILogger } from '../../logger/types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-storage:localstorage'); +import { logPrefix } from './index'; /** * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage. @@ -53,7 +52,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { } } } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); } } @@ -73,7 +72,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { } } } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); } } @@ -83,7 +82,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { * We cannot simply call `localStorage.clear()` since that implies removing user items from the storage. */ clear() { - this.log.info('Flushing Splits data from localStorage'); + this.log.info(logPrefix + 'Flushing Splits data from localStorage'); // collect item keys const len = localStorage.length; @@ -115,7 +114,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { return true; } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); return false; } } @@ -130,7 +129,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { return 1; } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); return 0; } } @@ -148,14 +147,14 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { // when using a new split query, we must update it at the store if (this.updateNewFilter) { - this.log.info('Split filter query was modified. Updating cache.'); + this.log.info(logPrefix + 'Split filter query was modified. Updating cache.'); const queryKey = this.keys.buildSplitsFilterQueryKey(); const queryString = this.splitFiltersValidation.queryString; try { if (queryString) localStorage.setItem(queryKey, queryString); else localStorage.removeItem(queryKey); } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); } this.updateNewFilter = false; } @@ -167,7 +166,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { this.hasSync = true; return true; } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); return false; } } @@ -274,7 +273,7 @@ export default class SplitsCacheInLocal extends AbstractSplitsCacheSync { }); } } catch (e) { - this.log.error(e); + this.log.error(logPrefix + e); } } // if the filter didn't change, nothing is done diff --git a/src/storages/inLocalStorage/index.ts b/src/storages/inLocalStorage/index.ts index 4ca9ee2d..6a4c8624 100644 --- a/src/storages/inLocalStorage/index.ts +++ b/src/storages/inLocalStorage/index.ts @@ -10,8 +10,8 @@ import MySegmentsCacheInMemory from '../inMemory/MySegmentsCacheInMemory'; import SplitsCacheInMemory from '../inMemory/SplitsCacheInMemory'; import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser'; import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-storage:localstorage'); + +export const logPrefix = 'storage:localstorage: '; export interface InLocalStorageOptions { prefix?: string @@ -28,7 +28,7 @@ export function InLocalStorage(options: InLocalStorageOptions = {}) { // Fallback to InMemoryStorage if LocalStorage API is not available if (!isLocalStorageAvailable()) { - params.log.warn('LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); + params.log.warn(logPrefix + 'LocalStorage API is unavailable. Fallbacking into default MEMORY storage'); return InMemoryStorageCSFactory(params); } diff --git a/src/storages/inRedis/EventsCacheInRedis.ts b/src/storages/inRedis/EventsCacheInRedis.ts index 839faee1..5a8caab5 100644 --- a/src/storages/inRedis/EventsCacheInRedis.ts +++ b/src/storages/inRedis/EventsCacheInRedis.ts @@ -4,8 +4,8 @@ import KeyBuilderSS from '../KeyBuilderSS'; import { Redis } from 'ioredis'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-storage:redis'); + +const logPrefix = 'storage:redis: '; export default class EventsCacheInRedis implements IEventsCacheAsync { @@ -33,7 +33,7 @@ export default class EventsCacheInRedis implements IEventsCacheAsync { // We use boolean values to signal successful queueing .then(() => true) .catch(err => { - this.log.error(`Error adding event to queue: ${err}.`); + this.log.error(logPrefix + `Error adding event to queue: ${err}.`); return false; }); } diff --git a/src/storages/inRedis/RedisAdapter.ts b/src/storages/inRedis/RedisAdapter.ts index fb7673ec..7d0636bc 100644 --- a/src/storages/inRedis/RedisAdapter.ts +++ b/src/storages/inRedis/RedisAdapter.ts @@ -4,8 +4,8 @@ import { merge, isString } from '../../utils/lang'; import { _Set, setToArray, ISet } from '../../utils/lang/sets'; import thenable from '../../utils/promise/thenable'; import timeout from '../../utils/promise/timeout'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-storage:redis-adapter'); + +const logPrefix = 'storage:redis-adapter: '; // If we ever decide to fully wrap every method, there's a Commander.getBuiltinCommands from ioredis. const METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', 'pipeline', 'expire', 'mget']; @@ -55,16 +55,16 @@ export default class RedisAdapter extends ioredis { _listenToEvents() { this.once('ready', () => { const commandsCount = this._notReadyCommandsQueue ? this._notReadyCommandsQueue.length : 0; - this.log.info(`Redis connection established. Queued commands: ${commandsCount}.`); + this.log.info(logPrefix + `Redis connection established. Queued commands: ${commandsCount}.`); this._notReadyCommandsQueue && this._notReadyCommandsQueue.forEach(queued => { - this.log.info(`Executing queued ${queued.name} command.`); + this.log.info(logPrefix + `Executing queued ${queued.name} command.`); queued.command().then(queued.resolve).catch(queued.reject); }); // After the SDK is ready for the first time we'll stop queueing commands. This is just so we can keep handling BUR for them. this._notReadyCommandsQueue = undefined; }); this.once('close', () => { - this.log.info('Redis connection closed.'); + this.log.info(logPrefix + 'Redis connection closed.'); }); } @@ -78,7 +78,7 @@ export default class RedisAdapter extends ioredis { const params = arguments; function commandWrapper() { - instance.log.debug(`Executing ${method}.`); + instance.log.debug(logPrefix + `Executing ${method}.`); // Return original method const result = originalMethod.apply(instance, params); @@ -93,7 +93,7 @@ export default class RedisAdapter extends ioredis { result.then(cleanUpRunningCommandsCb, cleanUpRunningCommandsCb); return timeout(instance._options.operationTimeout, result).catch(err => { - instance.log.error(`${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`); + instance.log.error(logPrefix + `${method} operation threw an error or exceeded configured timeout of ${instance._options.operationTimeout}ms. Message: ${err}`); // Handling is not the adapter responsibility. throw err; }); @@ -126,19 +126,19 @@ export default class RedisAdapter extends ioredis { setTimeout(function deferedDisconnect() { if (instance._runningCommands.size > 0) { - instance.log.info(`Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`); + instance.log.info(logPrefix + `Attempting to disconnect but there are ${instance._runningCommands.size} commands still waiting for resolution. Defering disconnection until those finish.`); Promise.all(setToArray(instance._runningCommands)) .then(() => { - instance.log.debug('Pending commands finished successfully, disconnecting.'); + instance.log.debug(logPrefix + 'Pending commands finished successfully, disconnecting.'); originalMethod.apply(instance, params); }) .catch(e => { - instance.log.warn(`Pending commands finished with error: ${e}. Proceeding with disconnection.`); + instance.log.warn(logPrefix + `Pending commands finished with error: ${e}. Proceeding with disconnection.`); originalMethod.apply(instance, params); }); } else { - instance.log.debug('No commands pending execution, disconnect.'); + instance.log.debug(logPrefix + 'No commands pending execution, disconnect.'); // Nothing pending, just proceed. originalMethod.apply(instance, params); } diff --git a/src/storages/inRedis/SplitsCacheInRedis.ts b/src/storages/inRedis/SplitsCacheInRedis.ts index 9e8d0201..c601b549 100644 --- a/src/storages/inRedis/SplitsCacheInRedis.ts +++ b/src/storages/inRedis/SplitsCacheInRedis.ts @@ -3,8 +3,8 @@ import KeyBuilderSS from '../KeyBuilderSS'; import { ISplitsCacheAsync } from '../types'; import { Redis } from 'ioredis'; import { ILogger } from '../../logger/types'; -// import { logFactory } from '../../logger/sdkLogger'; -// const log = logFactory('splitio-storage:redis'); + +const logPrefix = 'storage:redis: '; /** * Discard errors for an answer of multiple operations. @@ -83,7 +83,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { */ getSplit(name: string): Promise { if (this.redisError) { - this.log.error(this.redisError); + this.log.error(logPrefix + this.redisError); throw this.redisError; } @@ -137,14 +137,14 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { .then((ttCount: string | null | number) => { ttCount = parseInt(ttCount as string, 10); if (!isFiniteNumber(ttCount) || ttCount < 0) { - this.log.info(`Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`); + this.log.info(logPrefix + `Could not validate traffic type existance of ${trafficType} due to data corruption of some sorts.`); return false; } return ttCount > 0; }) .catch(e => { - this.log.error(`Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`); + this.log.error(logPrefix + `Could not validate traffic type existance of ${trafficType} due to an error: ${e}.`); // If there is an error, bypass the validation so the event can get tracked. return true; }); @@ -169,7 +169,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { */ getSplits(names: string[]): Promise> { if (this.redisError) { - this.log.error(this.redisError); + this.log.error(logPrefix + this.redisError); throw this.redisError; } @@ -183,7 +183,7 @@ export default class SplitsCacheInRedis implements ISplitsCacheAsync { return Promise.resolve(splits); }) .catch(e => { - this.log.error(`Could not grab splits due to an error: ${e}.`); + this.log.error(logPrefix + `Could not grab splits due to an error: ${e}.`); return Promise.reject(e); }); } From b1e2d7a4f13ad6cb2350ec047745a9ef747ef770 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 18 Mar 2021 20:14:08 -0300 Subject: [PATCH 42/58] remove some message codes for simplicity --- .../ga/__tests__/SplitToGa.spec.ts | 4 +- src/listeners/browser.ts | 5 +- src/listeners/node.ts | 12 ++-- src/logger/browser/debugLogger.ts | 3 +- src/logger/constants.ts | 35 ++------- src/logger/messages/debug.ts | 4 +- src/logger/messages/debugBrowser.ts | 8 --- src/logger/messages/debugNode.ts | 17 ----- src/logger/messages/errorNode.ts | 7 -- src/logger/messages/info.ts | 10 +-- src/logger/messages/warnNode.ts | 5 -- .../inRedis/__tests__/RedisAdapter.spec.ts | 71 ++++++++++--------- .../splitsParser/splitsParserFromFile.ts | 11 +-- src/sync/polling/pollingManagerSS.ts | 7 +- .../polling/syncTasks/segmentsSyncTask.ts | 10 +-- src/sync/syncManagerOnline.ts | 2 - .../logger/builtinLogger.ts | 27 ++++--- 17 files changed, 93 insertions(+), 145 deletions(-) delete mode 100644 src/logger/messages/debugBrowser.ts delete mode 100644 src/logger/messages/debugNode.ts delete mode 100644 src/logger/messages/errorNode.ts delete mode 100644 src/logger/messages/warnNode.ts diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index 2f486e8f..33581122 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -96,8 +96,8 @@ describe('SplitToGa', () => { // @ts-expect-error integration.queue('fake-data'); expect(loggerMock.warn.mock.calls).toEqual([ // Warn when creating and queueing while ga command queue does not exist - ['`ga` command queue not found. No hits will be sent until it is available.'], - ['`ga` command queue not found. No hit was sent.'] + ['split-to-ga: `ga` command queue not found. No hits will be sent until it is available.'], + ['split-to-ga: `ga` command queue not found. No hit was sent.'] ]); }); diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index 32f36130..db4dbd36 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -14,6 +14,7 @@ import { DEBUG_26, DEBUG_27 } from '../logger/constants'; // 'unload' event is used instead of 'beforeunload', since 'unload' is not a cancelable event, so no other listeners can stop the event from occurring. const UNLOAD_DOM_EVENT = 'unload'; +const LOG_EXTRA = 'for unload page event.'; /** * We'll listen for 'unload' event over the window object, since it's the standard way to listen page reload and close. @@ -39,7 +40,7 @@ export default class BrowserSignalListener implements ISignalListener { */ start() { if (typeof window !== 'undefined' && window.addEventListener) { - this.settings.log.debug(DEBUG_26); + this.settings.log.debug(DEBUG_26, [LOG_EXTRA]); window.addEventListener(UNLOAD_DOM_EVENT, this.flushData); } } @@ -51,7 +52,7 @@ export default class BrowserSignalListener implements ISignalListener { */ stop() { if (typeof window !== 'undefined' && window.removeEventListener) { - this.settings.log.debug(DEBUG_27); + this.settings.log.debug(DEBUG_27, [LOG_EXTRA]); window.removeEventListener(UNLOAD_DOM_EVENT, this.flushData); } } diff --git a/src/listeners/node.ts b/src/listeners/node.ts index 35d8f0e9..6d97d6c9 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -3,7 +3,9 @@ import { ISignalListener } from './types'; import thenable from '../utils/promise/thenable'; import { MaybeThenable } from '../dtos/types'; import { ISettings } from '../types'; -import { DEBUG_28, DEBUG_29, DEBUG_30, ERROR_1 } from '../logger/constants'; +import { CLEANUP_LB, DEBUG_26, DEBUG_27 } from '../logger/constants'; + +const LOG_EXTRA = 'for SIGTERM signal.'; /** * We'll listen for SIGTERM since it's the standard signal for server shutdown. @@ -22,13 +24,13 @@ export default class NodeSignalListener implements ISignalListener { } start() { - this.settings.log.debug(DEBUG_28); + this.settings.log.debug(DEBUG_26, [LOG_EXTRA]); // eslint-disable-next-line no-undef process.on('SIGTERM', this._sigtermHandler); } stop() { - this.settings.log.debug(DEBUG_29); + this.settings.log.debug(DEBUG_27, [LOG_EXTRA]); // eslint-disable-next-line no-undef process.removeListener('SIGTERM', this._sigtermHandler); } @@ -46,14 +48,14 @@ export default class NodeSignalListener implements ISignalListener { process.kill(process.pid, 'SIGTERM'); }; - this.settings.log.debug(DEBUG_30); + this.settings.log.debug(CLEANUP_LB + 'Split SDK graceful shutdown after SIGTERM.'); let handlerResult = null; try { handlerResult = this.handler(); } catch (err) { - this.settings.log.error(ERROR_1, [err]); + this.settings.log.error(CLEANUP_LB + `Error with Split SDK graceful shutdown: ${err}`); } if (thenable(handlerResult)) { diff --git a/src/logger/browser/debugLogger.ts b/src/logger/browser/debugLogger.ts index f0163454..119b2f05 100644 --- a/src/logger/browser/debugLogger.ts +++ b/src/logger/browser/debugLogger.ts @@ -3,10 +3,9 @@ import { codesError } from '../messages/error'; import { codesWarn } from '../messages/warn'; import { codesInfo } from '../messages/info'; import { codesDebug } from '../messages/debug'; -import { codesDebugBrowser } from '../messages/debugBrowser'; import { _Map } from '../../utils/lang/maps'; export const debugLogger = new Logger( 'splitio', { logLevel: 'DEBUG' }, - new _Map(codesError.concat(codesWarn, codesInfo, codesDebug, codesDebugBrowser)) + new _Map(codesError.concat(codesWarn, codesInfo, codesDebug)) ); diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 015c3078..4b396c20 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -1,4 +1,3 @@ -// commons export const DEBUG_ENGINE_COMBINER_AND = 0; export const DEBUG_1 = 1; export const DEBUG_2 = 2; @@ -25,6 +24,8 @@ export const DEBUG_22 = 22; export const DEBUG_23 = 23; export const DEBUG_24 = 24; export const DEBUG_25 = 25; +export const DEBUG_26 = 26; +export const DEBUG_27 = 27; export const DEBUG_32 = 32; export const DEBUG_33 = 33; export const DEBUG_36 = 36; @@ -39,23 +40,6 @@ export const DEBUG_49 = 49; export const DEBUG_50 = 50; export const DEBUG_SPLITS_FILTER = 51; -// browser -export const DEBUG_26 = 26; -export const DEBUG_27 = 27; - -// node -export const DEBUG_28 = 28; -export const DEBUG_29 = 29; -export const DEBUG_30 = 30; -export const DEBUG_39 = 39; -export const DEBUG_40 = 40; -export const DEBUG_41 = 41; -export const DEBUG_34 = 34; -export const DEBUG_35 = 35; -export const DEBUG_37 = 37; // @TODO remove since we already log it in syncTask debug log? -export const DEBUG_38 = 38; // @TODO remove since we already log it in syncTask debug log? - -// commons export const ERROR_0 = 300; export const ERROR_2 = 302; export const ERROR_CLIENT_LISTENER = 303; @@ -80,12 +64,6 @@ export const ERROR_EMPTY_ARRAY = 334; export const ERROR_INVALID_IMPRESSIONS_MODE = 338; export const ERROR_39 = 339; -// node -export const ERROR_1 = 301; -export const ERROR_API_KEY_INVALID = 308; -export const ERROR_6 = 306; - -// commons export const INFO_CLIENT_READY_FROM_CACHE = 100; export const INFO_CLIENT_READY = 101; export const INFO_2 = 102; @@ -109,7 +87,6 @@ export const INFO_19 = 119; export const INFO_20 = 120; export const INFO_21 = 121; -// commons export const WARN_ENGINE_INVALID_VALUE = 200; export const WARN_ENGINE_NO_ATTRIBUTES = 201; export const WARN_CLIENT_NO_LISTENER = 202; @@ -136,22 +113,20 @@ export const WARN_SPLITS_FILTER_EMPTY = 224; export const WARN_STORAGE_INVALID = 225; export const WARN_API_KEY = 226; -// node -export const WARN_3 = 203; - -// Log tags/categories +// Log prefixes/tags/categories export const SETTINGS_LB = 'settings'; export const ENGINE_LB = 'engine'; export const ENGINE_COMBINER_LB = ENGINE_LB + ':combiner: '; export const ENGINE_MATCHER_LB = ENGINE_LB + ':matcher: '; export const ENGINE_VALUE_LB = ENGINE_LB + ':value: '; export const SYNC_LB = 'sync'; +export const SYNC_MANAGER_LB = SYNC_LB + ':sync-manager: '; export const SYNC_OFFLINE_LB = SYNC_LB + ':offline: '; export const SYNC_STREAMING_LB = SYNC_LB + ':streaming: '; export const SYNC_SPLITS_LB = SYNC_LB + ':split-changes: '; export const SYNC_SEGMENTS_LB = SYNC_LB + ':segment-changes: '; export const SYNC_MYSEGMENTS_LB = SYNC_LB + ':my-segments: '; -export const SYNC_POLLING_LB = SYNC_LB + ':polling: '; +export const SYNC_POLLING_LB = SYNC_LB + ':polling-manager: '; export const SYNC_SUBMITTERS_LB = SYNC_LB + ':submitter: '; export const IMPRESSIONS_TRACKER_LB = 'impressions-tracker: '; export const EVENTS_TRACKER_LB = 'events-tracker: '; diff --git a/src/logger/messages/debug.ts b/src/logger/messages/debug.ts index 3a067b9b..714ff483 100644 --- a/src/logger/messages/debug.ts +++ b/src/logger/messages/debug.ts @@ -1,4 +1,4 @@ -import { DEBUG_ENGINE_COMBINER_AND, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_SPLITS_FILTER, SETTINGS_LB, ENGINE_LB, ENGINE_COMBINER_LB, ENGINE_MATCHER_LB, ENGINE_VALUE_LB, SYNC_OFFLINE_LB, IMPRESSIONS_TRACKER_LB, SYNC_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB } from '../constants'; +import { DEBUG_ENGINE_COMBINER_AND, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_SPLITS_FILTER, SETTINGS_LB, ENGINE_LB, ENGINE_COMBINER_LB, ENGINE_MATCHER_LB, ENGINE_VALUE_LB, SYNC_OFFLINE_LB, IMPRESSIONS_TRACKER_LB, SYNC_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, CLEANUP_LB, DEBUG_26, DEBUG_27 } from '../constants'; export const codesDebug: [number, string][] = [ // evaluator @@ -29,6 +29,8 @@ export const codesDebug: [number, string][] = [ [DEBUG_24, ENGINE_VALUE_LB + 'Extracted attribute [%s], [%s] will be used for matching.'], [DEBUG_25, ENGINE_LB + ':sanitize: Attempted to sanitize [%s] which should be of type [%s]. Sanitized and processed value => [%s]'], // SDK + [DEBUG_26, CLEANUP_LB + 'Registering cleanup handler %s'], + [DEBUG_27, CLEANUP_LB + 'Deregistering cleanup handler %s'], [DEBUG_32, ' Retrieving default SDK client.'], [DEBUG_33, ' Retrieving existing SDK client.'], // synchronizer diff --git a/src/logger/messages/debugBrowser.ts b/src/logger/messages/debugBrowser.ts deleted file mode 100644 index df641ca9..00000000 --- a/src/logger/messages/debugBrowser.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { CLEANUP_LB, DEBUG_26, DEBUG_27 } from '../constants'; - -const HANDLER_LB = ' flush handler when unload page event is triggered.'; - -export const codesDebugBrowser: [number, string][] = [ - [DEBUG_26, CLEANUP_LB + 'Registering' + HANDLER_LB], - [DEBUG_27, CLEANUP_LB + 'Deregistering' + HANDLER_LB], -]; diff --git a/src/logger/messages/debugNode.ts b/src/logger/messages/debugNode.ts deleted file mode 100644 index 0138a56e..00000000 --- a/src/logger/messages/debugNode.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { DEBUG_28, DEBUG_29, DEBUG_30, DEBUG_39, DEBUG_40, DEBUG_41, DEBUG_34, DEBUG_35, DEBUG_37, DEBUG_38, CLEANUP_LB, SYNC_OFFLINE_LB, SYNC_POLLING_LB, SYNC_SEGMENTS_LB } from '../constants'; - -const HANDLER_LB = ' cleanup handlers.'; - -export const codesDebugNode: [number, string][] = [ - [DEBUG_28, CLEANUP_LB + 'Registering' + HANDLER_LB], - [DEBUG_29, CLEANUP_LB + 'Deregistering' + HANDLER_LB], - [DEBUG_30, CLEANUP_LB + 'Split SDK graceful shutdown after SIGTERM.'], - // synchronizer - [DEBUG_39, SYNC_SEGMENTS_LB + 'Processed %s with till = %s. Added: %s. Removed: %s'], - [DEBUG_40, SYNC_SEGMENTS_LB + 'Processing segment %s'], - [DEBUG_41, SYNC_SEGMENTS_LB + 'Started segments update'], - [DEBUG_34, SYNC_OFFLINE_LB + 'Ignoring empty line or comment at #%s'], - [DEBUG_35, SYNC_OFFLINE_LB + 'Ignoring line since it does not have exactly two columns #%s'], - [DEBUG_37, SYNC_POLLING_LB + 'Splits will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? - [DEBUG_38, SYNC_POLLING_LB + 'Segments will be refreshed each %s millis'], // @TODO remove since we already log it in syncTask debug log? -]; diff --git a/src/logger/messages/errorNode.ts b/src/logger/messages/errorNode.ts deleted file mode 100644 index ff75d031..00000000 --- a/src/logger/messages/errorNode.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ERROR_1, ERROR_API_KEY_INVALID, ERROR_6, SETTINGS_LB, CLEANUP_LB, SYNC_OFFLINE_LB } from '../constants'; - -export const codesErrorNode: [number, string][] = [ - [ERROR_1, CLEANUP_LB + 'Error with Split graceful shutdown: %s'], - [ERROR_6, SYNC_OFFLINE_LB + 'Ignoring entry on YAML since the format is incorrect.'], - [ERROR_API_KEY_INVALID, SETTINGS_LB+': you passed a Client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.'], -]; diff --git a/src/logger/messages/info.ts b/src/logger/messages/info.ts index 5cb751a1..665ca8d8 100644 --- a/src/logger/messages/info.ts +++ b/src/logger/messages/info.ts @@ -1,4 +1,4 @@ -import { INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21, EVENTS_TRACKER_LB, SYNC_POLLING_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, SYNC_SUBMITTERS_LB, IMPRESSIONS_TRACKER_LB } from '../constants'; +import { INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21, EVENTS_TRACKER_LB, SYNC_MANAGER_LB, SYNC_POLLING_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, SYNC_SUBMITTERS_LB, IMPRESSIONS_TRACKER_LB } from '../constants'; const READY_MSG = 'Split SDK is ready'; @@ -12,6 +12,7 @@ export const codesInfo: [number, string][] = [ [INFO_4, ' New shared client instance created.'], [INFO_5, ' New Split SDK instance created.'], [INFO_6, ' Manager instance retrieved.'], + [INFO_21, EVENTS_TRACKER_LB + 'Successfully qeued %s'], // synchronizer [INFO_7, SYNC_POLLING_LB + 'Turning segments data polling %s.'], [INFO_8, SYNC_POLLING_LB + 'Starting polling'], @@ -24,8 +25,7 @@ export const codesInfo: [number, string][] = [ [INFO_13, SYNC_STREAMING_LB + 'Connecting to streaming.'], [INFO_14, SYNC_STREAMING_LB + 'Streaming is disabled for given Api key. Switching to polling mode.'], [INFO_15, SYNC_STREAMING_LB + 'Disconnecting from streaming.'], - [INFO_18, SYNC_STREAMING_LB + 'Streaming not available. Starting polling.'], - [INFO_19, SYNC_STREAMING_LB + 'Streaming couldn\'t connect. Continue polling.'], - [INFO_20, SYNC_STREAMING_LB + 'Streaming (re)connected. Syncing and stopping polling.'], - [INFO_21, EVENTS_TRACKER_LB + 'Successfully qeued %s'] + [INFO_18, SYNC_MANAGER_LB + 'Streaming not available. Starting polling.'], + [INFO_19, SYNC_MANAGER_LB + 'Streaming couldn\'t connect. Continue polling.'], + [INFO_20, SYNC_MANAGER_LB + 'Streaming (re)connected. Syncing and stopping polling.'], ]; diff --git a/src/logger/messages/warnNode.ts b/src/logger/messages/warnNode.ts deleted file mode 100644 index 1a5692b8..00000000 --- a/src/logger/messages/warnNode.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SYNC_OFFLINE_LB, WARN_3 } from '../constants'; - -export const codesWarnNode: [number, string][] = [ - [WARN_3, SYNC_OFFLINE_LB + '.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'], -]; diff --git a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts index 93c4bdb1..918c895e 100644 --- a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts +++ b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts @@ -6,6 +6,7 @@ import { _Set, setToArray } from '../../../utils/lang/sets'; // Mocking sdkLogger import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; +const logPrefix = 'storage:redis-adapter: '; // Mocking ioredis @@ -155,23 +156,23 @@ describe('STORAGE Redis Adapter', () => { }); test('instance methods - _listenToEvents', (done) => { - expect(ioredisMock.once.mock.calls.length).toBe(0); // Control assertion - expect(ioredisMock[METHODS_TO_PROMISE_WRAP[0]].mock.calls.length).toBe(0); // Control assertion + expect(ioredisMock.once).not.toBeCalled(); // Control assertion + expect(ioredisMock[METHODS_TO_PROMISE_WRAP[0]]).not.toBeCalled(); // Control assertion const instance = new RedisAdapter(loggerMock, { url: 'redis://localhost:6379/0' }); - expect(ioredisMock.once.mock.calls.length).toBe(2); // If the method was called, it should have called the `once` function twice. If that it the case we can assume that the method was called on creation. + expect(ioredisMock.once).toBeCalledTimes(2); // If the method was called, it should have called the `once` function twice. If that it the case we can assume that the method was called on creation. // Reset stubs again, we'll check the behaviour calling the method directly. clearAllMocks(); - expect(ioredisMock.once.mock.calls.length).toBe(0); // Control assertion - expect(ioredisMock[METHODS_TO_PROMISE_WRAP[METHODS_TO_PROMISE_WRAP.length - 1]].mock.calls.length).toBe(0); // Control assertion + expect(ioredisMock.once).not.toBeCalled(); // Control assertion + expect(ioredisMock[METHODS_TO_PROMISE_WRAP[METHODS_TO_PROMISE_WRAP.length - 1]]).not.toBeCalled(); // Control assertion instance._listenToEvents(); - expect(ioredisMock.once.mock.calls.length).toBe(2); // The "once" method of the instance should be called twice. + expect(ioredisMock.once).toBeCalledTimes(2); // The "once" method of the instance should be called twice. const firstCallArgs = ioredisMock.once.mock.calls[0]; @@ -183,21 +184,21 @@ describe('STORAGE Redis Adapter', () => { expect(secondCallArgs[0]).toBe('close'); // First argument for the first call should be the "close" event. expect(typeof secondCallArgs[1]).toBe('function'); // second argument for the first call should be a callback function. - expect(loggerMock.warn.mock.calls.length).toBe(0); // Control assertion + expect(loggerMock.warn).not.toBeCalled(); // Control assertion secondCallArgs[1](); // Execute the callback for "close" - expect(loggerMock.info.mock.calls.length).toBe(1); // The callback for the "close" event will only log info to the user about what is going on. - expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection closed.']); // The callback for the "close" event will only log info to the user about what is going on. + expect(loggerMock.info).toBeCalledTimes(1); // The callback for the "close" event will only log info to the user about what is going on. + expect(loggerMock.info.mock.calls[0]).toEqual([logPrefix + 'Redis connection closed.']); // The callback for the "close" event will only log info to the user about what is going on. loggerMock.info.mockClear(); - expect(loggerMock.info.mock.calls.length).toBe(0); // Control assertion + expect(loggerMock.info).not.toBeCalled(); // Control assertion expect(Array.isArray(instance._notReadyCommandsQueue)).toBe(true); // Control assertion // Without any offline commands queued, execute the callback for "ready" firstCallArgs[1](); - expect(loggerMock.info.mock.calls.length).not.toBe(0); // The callback for the "ready" event will inform the user about the trigger. - expect(loggerMock.info.mock.calls[0]).toEqual(['Redis connection established. Queued commands: 0.']); // The callback for the "ready" event will inform the user about the trigger. + expect(loggerMock.info).toBeCalledTimes(1); // The callback for the "ready" event will inform the user about the trigger. + expect(loggerMock.info).toBeCalledWith(logPrefix + 'Redis connection established. Queued commands: 0.'); // The callback for the "ready" event will inform the user about the trigger. expect(instance._notReadyCommandsQueue).toBe(undefined); // After the DB is ready, it will clean up the offline commands queue so we do not queue commands anymore. // Don't do this at home @@ -219,19 +220,19 @@ describe('STORAGE Redis Adapter', () => { // execute the callback for "ready" once more firstCallArgs[1](); - expect(loggerMock.info.mock.calls.length).toBe(3); // If we had queued commands, it will log the event (1 call) as well as each executed command (n calls). + expect(loggerMock.info).toBeCalledTimes(3); // If we had queued commands, it will log the event (1 call) as well as each executed command (n calls). expect(loggerMock.info.mock.calls).toEqual([ - ['Redis connection established. Queued commands: 2.'], // The callback for the "ready" event will inform the user about the trigger and the amount of queued commands. - ['Executing queued GET command.'], // If we had queued, it will log the event as well as each executed command. - ['Executing queued SET command.'] // If we had queued commands, it will log the event as well as each executed command. + [logPrefix + 'Redis connection established. Queued commands: 2.'], // The callback for the "ready" event will inform the user about the trigger and the amount of queued commands. + [logPrefix + 'Executing queued GET command.'], // If we had queued, it will log the event as well as each executed command. + [logPrefix + 'Executing queued SET command.'] // If we had queued commands, it will log the event as well as each executed command. ]); - expect(queuedGetCommand.command.mock.calls.length).toBe(1); // It will execute each queued command. + expect(queuedGetCommand.command).toBeCalledTimes(1); // It will execute each queued command. setTimeout(() => { // Remember this is tied to a promise. - expect(queuedGetCommand.resolve.mock.calls.length).not.toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. - expect(queuedGetCommand.reject.mock.calls.length).toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. - expect(queuedSetCommand.reject.mock.calls.length).not.toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. - expect(queuedSetCommand.resolve.mock.calls.length).toBe(0); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. + expect(queuedGetCommand.resolve).toBeCalled(); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. + expect(queuedGetCommand.reject).not.toBeCalled(); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. + expect(queuedSetCommand.reject).toBeCalled(); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. + expect(queuedSetCommand.resolve).not.toBeCalled(); // And depending on what happens with the command promise, it will call the resolve or reject function for the promise wrapper. done(); }, 5); @@ -245,7 +246,7 @@ describe('STORAGE Redis Adapter', () => { forEach(METHODS_TO_PROMISE_WRAP, methodName => { expect(instance[methodName]).not.toBe(ioredisMock[methodName]); // Method "${methodName}" from ioredis library should be wrapped. - expect(ioredisMock[methodName].mock.calls.length).toBe(0); // Checking that the method was not called yet. + expect(ioredisMock[methodName]).not.toBeCalled(); // Checking that the method was not called yet. const startingQueueLength = instance._notReadyCommandsQueue.length; @@ -267,12 +268,12 @@ describe('STORAGE Redis Adapter', () => { forEach(METHODS_TO_PROMISE_WRAP, (methodName, index) => { // We do NOT have the commands queue on this state, so a call for this methods will execute the command. - expect(ioredisMock[methodName].mock.calls.length).toBe(0); // Control assertion - Original method (${methodName}) was not called yet + expect(ioredisMock[methodName]).not.toBeCalled(); // Control assertion - Original method (${methodName}) was not called yet const previousTimeoutCalls = timeout.mock.calls.length; let previousRunningCommandsSize = instance._runningCommands.size; instance[methodName](methodName).catch(() => { }); // Swallow exception so it's not spread to logs. - expect(ioredisMock[methodName].mock.calls.length).not.toBe(0); // Original method (${methodName}) is called right away (through wrapper) when we are not queueing anymore. + expect(ioredisMock[methodName]).toBeCalled(); // Original method (${methodName}) is called right away (through wrapper) when we are not queueing anymore. expect(instance._runningCommands.size).toBe(previousRunningCommandsSize + 1); // If the result of the operation was a thenable it will add the item to the running commands queue. expect(timeout.mock.calls.length).toBe(previousTimeoutCalls + 1); // The promise returned by the original method should have a timeout wrapper. @@ -286,7 +287,7 @@ describe('STORAGE Redis Adapter', () => { commandTimeoutResolver.rej('test'); setTimeout(() => { // Allow the promises to tick. expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes with error, it's promise is removed from the instance._runningCommands queue. - expect(loggerMock.error.mock.calls[index]).toEqual([`${methodName} operation threw an error or exceeded configured timeout of 5000ms. Message: test`]); // The log error method should be called with the corresponding messages, depending on the method, error and operationTimeout. + expect(loggerMock.error.mock.calls[index]).toEqual([`${logPrefix}${methodName} operation threw an error or exceeded configured timeout of 5000ms. Message: test`]); // The log error method should be called with the corresponding messages, depending on the method, error and operationTimeout. }, 0); }); @@ -310,7 +311,7 @@ describe('STORAGE Redis Adapter', () => { commandTimeoutResolver.res('test'); setTimeout(() => { // Allow the promises to tick. - expect(loggerMock.error.mock.calls.length).toBe(0); // No error should be logged + expect(loggerMock.error).not.toBeCalled(); // No error should be logged expect(instance._runningCommands.has(commandTimeoutResolver.originalPromise)).toBe(false); // After a command finishes successfully, it's promise is removed from the instance._runningCommands queue. }, 0); }); @@ -330,11 +331,11 @@ describe('STORAGE Redis Adapter', () => { // Call the method. // Note that there are no commands on the queue for this first run. instance.disconnect(); - expect(ioredisMock.disconnect.mock.calls.length).toBe(0); // Original method should not be called right away. + expect(ioredisMock.disconnect).not.toBeCalled(); // Original method should not be called right away. setTimeout(() => { // o queued commands timeout wrapper. - expect(loggerMock.debug.mock.calls).toEqual([['No commands pending execution, disconnect.']]); - expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously + expect(loggerMock.debug.mock.calls).toEqual([[logPrefix + 'No commands pending execution, disconnect.']]); + expect(ioredisMock.disconnect).toBeCalledTimes(1); // Original method should have been called once, asynchronously loggerMock.debug.mockClear(); ioredisMock.disconnect.mockClear(); @@ -346,12 +347,12 @@ describe('STORAGE Redis Adapter', () => { rejectedPromise.catch(() => { }); // Swallow the unhandled to avoid unhandledRejection warns setTimeout(() => { // queued with rejection timeout wrapper - expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 2 commands still waiting for resolution. Defering disconnection until those finish.']]); + expect(loggerMock.info.mock.calls).toEqual([[logPrefix + 'Attempting to disconnect but there are 2 commands still waiting for resolution. Defering disconnection until those finish.']]); Promise.all(setToArray(instance._runningCommands)).catch(e => { setImmediate(() => { // Allow the callback to execute before checking. - expect(loggerMock.warn.mock.calls[0]).toEqual([`Pending commands finished with error: ${e}. Proceeding with disconnection.`]); // Should warn about the error but tell user that will disconnect anyways. - expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously + expect(loggerMock.warn.mock.calls[0]).toEqual([`${logPrefix}Pending commands finished with error: ${e}. Proceeding with disconnection.`]); // Should warn about the error but tell user that will disconnect anyways. + expect(ioredisMock.disconnect).toBeCalledTimes(1); // Original method should have been called once, asynchronously loggerMock.info.mockClear(); loggerMock.warn.mockClear(); @@ -366,12 +367,12 @@ describe('STORAGE Redis Adapter', () => { instance._runningCommands.add(Promise.resolve()); setTimeout(() => { - expect(loggerMock.info.mock.calls).toEqual([['Attempting to disconnect but there are 4 commands still waiting for resolution. Defering disconnection until those finish.']]); + expect(loggerMock.info.mock.calls).toEqual([[logPrefix + 'Attempting to disconnect but there are 4 commands still waiting for resolution. Defering disconnection until those finish.']]); Promise.all(setToArray(instance._runningCommands)).then(() => { // This one will go through success path setImmediate(() => { - expect(loggerMock.debug.mock.calls).toEqual([['Pending commands finished successfully, disconnecting.']]); - expect(ioredisMock.disconnect.mock.calls.length).toBe(1); // Original method should have been called once, asynchronously + expect(loggerMock.debug.mock.calls).toEqual([[logPrefix + 'Pending commands finished successfully, disconnecting.']]); + expect(ioredisMock.disconnect).toBeCalledTimes(1); // Original method should have been called once, asynchronously }); }); }, 10); diff --git a/src/sync/offline/splitsParser/splitsParserFromFile.ts b/src/sync/offline/splitsParser/splitsParserFromFile.ts index 71dcbaec..b56052c6 100644 --- a/src/sync/offline/splitsParser/splitsParserFromFile.ts +++ b/src/sync/offline/splitsParser/splitsParserFromFile.ts @@ -9,7 +9,8 @@ import parseCondition, { IMockSplitEntry } from './parseCondition'; import { ISplitPartial } from '../../../dtos/types'; import { SplitIO } from '../../../types'; import { ILogger } from '../../../logger/types'; -import { DEBUG_34, DEBUG_35, ERROR_6, WARN_3 } from '../../../logger/constants'; + +const logPrefix = 'sync:offline:splits-fetcher: '; type IYamlSplitEntry = Record @@ -59,12 +60,12 @@ function readSplitConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFileP let tuple: string | string[] = line.trim(); if (tuple === '' || tuple.charAt(0) === '#') { - log.debug(DEBUG_34, [index]); + log.debug(logPrefix + `Ignoring empty line or comment at #${index}`); } else { tuple = tuple.split(/\s+/); if (tuple.length !== 2) { - log.debug(DEBUG_35, [index]); + log.debug(logPrefix + `Ignoring line since it does not have exactly two columns #${index}`); } else { const splitName = tuple[SPLIT_POSITION]; const condition = parseCondition({ treatment: tuple[TREATMENT_POSITION] }); @@ -101,7 +102,7 @@ function readYAMLConfigFile(log: ILogger, filePath: SplitIO.MockedFeaturesFilePa const splitName = Object.keys(splitEntry)[0]; if (!splitName || !isString(splitEntry[splitName].treatment)) - log.error(ERROR_6); + log.error(logPrefix + 'Ignoring entry on YAML since the format is incorrect.'); const mockData = splitEntry[splitName]; @@ -166,7 +167,7 @@ export default function splitsParserFromFile({ features, log }: { features?: Spl // If we have a filePath, it means the extension is correct, choose the parser. if (endsWith(filePath, '.split')) { - log.warn(WARN_3); + log.warn(logPrefix + '.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.'); mockData = readSplitConfigFile(log, filePath); } else { mockData = readYAMLConfigFile(log, filePath); diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index 587e25cc..f6cf4396 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -6,8 +6,7 @@ import { ISplitApi } from '../../services/types'; import { ISettings } from '../../types'; import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types'; import thenable from '../../utils/promise/thenable'; -import { INFO_8, INFO_9 } from '../../logger/constants'; -import { DEBUG_37, DEBUG_38 } from '../../logger/constants'; +import { INFO_8, INFO_9, SYNC_POLLING_LB } from '../../logger/constants'; /** * Expose start / stop mechanism for pulling data from services. @@ -31,8 +30,8 @@ export default function pollingManagerSSFactory( // Start periodic fetching (polling) start() { log.info(INFO_8); - log.debug(DEBUG_37, [settings.scheduler.featuresRefreshRate]); // @TODO remove since we already log it in syncTask debug log? - log.debug(DEBUG_38, [settings.scheduler.segmentsRefreshRate]); // @TODO remove since we already log it in syncTask debug log? + log.debug(SYNC_POLLING_LB + `Splits will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`); + log.debug(SYNC_POLLING_LB + `Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`); const startingUp = splitsSyncTask.start(); if (thenable(startingUp)) { diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index e9e43e50..359a5620 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -11,7 +11,7 @@ import { IFetchSegmentChanges } from '../../../services/types'; import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; -import { DEBUG_41, DEBUG_40, DEBUG_39, ERROR_API_KEY_INVALID } from '../../../logger/constants'; +import { SETTINGS_LB, SYNC_SEGMENTS_LB } from '../../../logger/constants'; type ISegmentChangesUpdater = (segmentNames?: string[], noCache?: boolean, fetchOnlyNew?: boolean) => Promise @@ -48,7 +48,7 @@ function segmentChangesUpdaterFactory( * This param is used by SplitUpdateWorker on server-side SDK, to fetch new registered segments on SPLIT_UPDATE notifications. */ return function segmentChangesUpdater(segmentNames?: string[], noCache?: boolean, fetchOnlyNew?: boolean) { - log.debug(DEBUG_41); + log.debug(SYNC_SEGMENTS_LB + 'Started segments update'); // If not a segment name provided, read list of available segments names to be updated. let segments = segmentNames ? segmentNames : segmentsCache.getRegisteredSegments(); @@ -61,7 +61,7 @@ function segmentChangesUpdaterFactory( const segmentName = segments[index]; const since = segmentsCache.getChangeNumber(segmentName); - log.debug(DEBUG_40, [segmentName]); + log.debug(SYNC_SEGMENTS_LB + `Processing segment ${segmentName}`); updaters.push(segmentChangesFetcher(since, segmentName, noCache, _promiseDecorator).then(function (changes) { let changeNumber = -1; @@ -73,7 +73,7 @@ function segmentChangesUpdaterFactory( changeNumber = x.till; } - log.debug(DEBUG_39, [segmentName, x.till, x.added.length, x.removed.length]); + log.debug(SYNC_SEGMENTS_LB + `Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`); }); return changeNumber; @@ -97,7 +97,7 @@ function segmentChangesUpdaterFactory( if (error.statusCode === 403) { // @TODO although factory status is destroyed, synchronization is not stopped readiness.destroy(); - log.error(ERROR_API_KEY_INVALID); + log.error(SETTINGS_LB + 'you passed a client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.'); } return false; diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index 6831e4bd..4a0a0099 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -9,8 +9,6 @@ import { IPushManagerFactoryParams, IPushManager, IPushManagerCS } from './strea import { IPollingManager, IPollingManagerCS, IPollingManagerFactoryParams } from './polling/types'; import { PUSH_SUBSYSTEM_UP, PUSH_SUBSYSTEM_DOWN } from './streaming/constants'; import { INFO_18, INFO_19, INFO_20 } from '../logger/constants'; -// import { logFactory } from '../logger/sdkLogger'; -// export const log = logFactory('splitio-sync:sync-manager'); /** * Online SyncManager factory. diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index 358cb7f0..b5f108cf 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -3,6 +3,7 @@ import { ILogger } from '../../../logger/types'; import { LogLevel } from '../../../types'; import { isLocalStorageAvailable } from '../../env/isLocalStorageAvailable'; import { isNode } from '../../env/isNode'; +import { IMap } from '../../lang/maps'; // @TODO when integrating with other packages, find the best way to handle initial state per environment const LS_KEY = 'splitio_debug'; @@ -47,19 +48,25 @@ export function getLogLevel(debugValue: unknown): LogLevel | undefined { } /** - * Validates the `debug` property at config and use it to set the log level. - * - * @param settings user config object - * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. + * Factory of logger validator, which validates the `debug` property at config and creates a logger instance with the provided `debug` log level. */ -export function validateLogger(settings: { debug: unknown} ): ILogger { +export function validateLoggerFactory(msgCodes?: IMap) { - const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; + /** + * Validates the `debug` property at config and use it to set the log level. + * + * @param settings user config object + * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. + */ + return function validateLogger(settings: { debug: unknown }): ILogger { - const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }); + const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; - // logs error if the provided settings debug value is invalid - if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); + const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }, msgCodes); - return log; + // logs error if the provided settings debug value is invalid + if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); + + return log; + }; } From 88b9c4fc703a52df587a603a43ab4b6249e17087 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 19 Mar 2021 14:40:51 -0300 Subject: [PATCH 43/58] comments --- src/logger/constants.ts | 7 ++++ src/logger/messages/error.ts | 2 +- .../logger/builtinLogger.ts | 34 +++++++++---------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 4b396c20..2855ae13 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -1,3 +1,10 @@ +/** + * Message codes used to trim string log messages from commons and client-side API modules, + * in order to reduce the minimal SDK size for Browser and eventually other client-side environments. + * + * Modules related to the server-side API (e.g., segmentsSyncTask), platform-specific components (e.g., signal listeners) + * and pluggable components (e.g., pluggable integrations & storages) can use the logger with string literals. + */ export const DEBUG_ENGINE_COMBINER_AND = 0; export const DEBUG_1 = 1; export const DEBUG_2 = 2; diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index 931bc1f1..b3645e5a 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -5,7 +5,7 @@ export const codesError: [number, string][] = [ [ERROR_0, ENGINE_COMBINER_LB + 'Invalid Split provided, no valid conditions found'], // SDK [ERROR_2, 'logger: Invalid Log Level - No changes to the logs will be applied.'], - [ERROR_4, ' Manager instance is not available.'], + [ERROR_4, ' Manager instance is not available.'], // @TODO remove if the manager is not pluggable [ERROR_5, ' The SDK will not get ready. Reason: %s'], // synchronizer [ERROR_7, SYNC_OFFLINE_LB + 'There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index b5f108cf..2ef50b97 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -3,7 +3,13 @@ import { ILogger } from '../../../logger/types'; import { LogLevel } from '../../../types'; import { isLocalStorageAvailable } from '../../env/isLocalStorageAvailable'; import { isNode } from '../../env/isNode'; -import { IMap } from '../../lang/maps'; +import { codesError } from '../../../logger/messages/error'; +import { codesWarn } from '../../../logger/messages/warn'; +import { codesInfo } from '../../../logger/messages/info'; +import { codesDebug } from '../../../logger/messages/debug'; +import { _Map } from '../../lang/maps'; + +const allCodes = new _Map(codesError.concat(codesWarn, codesInfo, codesDebug)); // @TODO when integrating with other packages, find the best way to handle initial state per environment const LS_KEY = 'splitio_debug'; @@ -48,25 +54,19 @@ export function getLogLevel(debugValue: unknown): LogLevel | undefined { } /** - * Factory of logger validator, which validates the `debug` property at config and creates a logger instance with the provided `debug` log level. + * Validates the `debug` property at config and use it to set the log level. + * + * @param settings user config object + * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. */ -export function validateLoggerFactory(msgCodes?: IMap) { - - /** - * Validates the `debug` property at config and use it to set the log level. - * - * @param settings user config object - * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. - */ - return function validateLogger(settings: { debug: unknown }): ILogger { +export function validateLogger(settings: { debug: unknown }): ILogger { - const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; + const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; - const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }, msgCodes); + const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }, allCodes); - // logs error if the provided settings debug value is invalid - if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); + // logs error if the provided settings debug value is invalid + if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); - return log; - }; + return log; } From c7f43f17db6c0c22af87510f034dc529730b38c8 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 19 Mar 2021 15:41:20 -0300 Subject: [PATCH 44/58] moved category to logger options, and optimized methods --- src/logger/__tests__/index.spec.ts | 4 +- src/logger/__tests__/sdkLogger.spec.ts | 2 +- src/logger/browser/debugLogger.ts | 2 +- src/logger/browser/errorLogger.ts | 2 +- src/logger/browser/infoLogger.ts | 2 +- src/logger/browser/warnLogger.ts | 2 +- src/logger/index.ts | 55 ++++++++++--------- src/logger/types.ts | 1 + .../logger/builtinLogger.ts | 2 +- .../logger/pluggableLogger.ts | 8 +-- 10 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index b56491d2..3a08510d 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -27,7 +27,7 @@ test('SPLIT LOGGER / LogLevels exposed mappings', () => { test('SPLIT LOGGER / Logger class shape', () => { expect(typeof Logger).toBe('function'); // Logger should be a class we can instantiate. - const logger = new Logger('test-category'); + const logger = new Logger({ prefix: 'test-category' }); expect(typeof logger.debug).toBe('function'); // instance.debug should be a method. expect(typeof logger.info).toBe('function'); // instance.info should be a method. @@ -57,7 +57,7 @@ function testLogLevels(levelToTest: LogLevel) { let testForNoLog = false; const logMethod = levelToTest.toLowerCase(); const logCategory = `test-category-${logMethod}`; - const instance = new Logger(logCategory, { showLevel }); + const instance = new Logger({ prefix: logCategory, showLevel }); LOG_LEVELS_IN_ORDER.forEach((logLevel, i) => { const logMsg = `Test log for level ${levelToTest} with showLevel: ${showLevel} ${logLevelLogsCounter}`; diff --git a/src/logger/__tests__/sdkLogger.spec.ts b/src/logger/__tests__/sdkLogger.spec.ts index 6776e679..6fc87787 100644 --- a/src/logger/__tests__/sdkLogger.spec.ts +++ b/src/logger/__tests__/sdkLogger.spec.ts @@ -3,7 +3,7 @@ import { Logger, LogLevels } from '../index'; test('LoggerAPI / methods and props', () => { // creates a LoggerAPI instance - const logger = new Logger('category'); + const logger = new Logger(); const API = createLoggerAPI(logger); expect(typeof API).toBe('object'); // Our logger should expose an API object. diff --git a/src/logger/browser/debugLogger.ts b/src/logger/browser/debugLogger.ts index 119b2f05..d1a2aee8 100644 --- a/src/logger/browser/debugLogger.ts +++ b/src/logger/browser/debugLogger.ts @@ -6,6 +6,6 @@ import { codesDebug } from '../messages/debug'; import { _Map } from '../../utils/lang/maps'; export const debugLogger = new Logger( - 'splitio', { logLevel: 'DEBUG' }, + { logLevel: 'DEBUG' }, new _Map(codesError.concat(codesWarn, codesInfo, codesDebug)) ); diff --git a/src/logger/browser/errorLogger.ts b/src/logger/browser/errorLogger.ts index 7423d7fc..33aaa4a5 100644 --- a/src/logger/browser/errorLogger.ts +++ b/src/logger/browser/errorLogger.ts @@ -3,6 +3,6 @@ import { codesError } from '../messages/error'; import { _Map } from '../../utils/lang/maps'; export const errorLogger = new Logger( - 'splitio', { logLevel: 'ERROR' }, + { logLevel: 'ERROR' }, new _Map(codesError) ); diff --git a/src/logger/browser/infoLogger.ts b/src/logger/browser/infoLogger.ts index c88c7c8d..70eada90 100644 --- a/src/logger/browser/infoLogger.ts +++ b/src/logger/browser/infoLogger.ts @@ -5,6 +5,6 @@ import { codesInfo } from '../messages/info'; import { _Map } from '../../utils/lang/maps'; export const infoLogger = new Logger( - 'splitio', { logLevel: 'INFO' }, + { logLevel: 'INFO' }, new _Map(codesError.concat(codesWarn, codesInfo)) ); diff --git a/src/logger/browser/warnLogger.ts b/src/logger/browser/warnLogger.ts index 348d4284..5af9440c 100644 --- a/src/logger/browser/warnLogger.ts +++ b/src/logger/browser/warnLogger.ts @@ -4,6 +4,6 @@ import { codesWarn } from '../messages/warn'; import { _Map } from '../../utils/lang/maps'; export const warnLogger = new Logger( - 'splitio', { logLevel: 'WARN' }, + { logLevel: 'WARN' }, new _Map(codesError.concat(codesWarn)) ); diff --git a/src/logger/index.ts b/src/logger/index.ts index 27b43ab0..afb3b8ac 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -12,6 +12,14 @@ export const LogLevels: { [level: string]: LogLevel } = { NONE: 'NONE' }; +const logLevelRanks = { + DEBUG: 1, + INFO: 2, + WARN: 3, + ERROR: 4, + NONE: 5 +}; + export function isLogLevelString(str: string): str is LogLevel { return !!find(LogLevels, (lvl: string) => str === lvl); } @@ -24,53 +32,53 @@ function sprintf(format: string = '', args: any[] = []): string { } const defaultOptions = { + prefix: 'splitio', logLevel: LogLevels.NONE, showLevel: true, }; export class Logger implements ILogger { - private category: string; private options: Required; private codes: IMap; + private logLevel: number; - constructor(category: string, options?: ILoggerOptions, codes?: IMap) { - this.category = category; + constructor(options?: ILoggerOptions, codes?: IMap) { this.options = objectAssign({}, defaultOptions, options); this.codes = codes || new _Map(); + this.logLevel = logLevelRanks[this.options.logLevel]; } setLogLevel(logLevel: LogLevel) { this.options.logLevel = logLevel; + this.logLevel = logLevelRanks[logLevel]; } debug(msg: string | number, args?: any[]) { - this._log(LogLevels.DEBUG, msg, args); + if (this._shouldLog(logLevelRanks.DEBUG)) this._log(LogLevels.DEBUG, msg, args); } info(msg: string | number, args?: any[]) { - this._log(LogLevels.INFO, msg, args); + if (this._shouldLog(logLevelRanks.INFO)) this._log(LogLevels.INFO, msg, args); } warn(msg: string | number, args?: any[]) { - this._log(LogLevels.WARN, msg, args); + if (this._shouldLog(logLevelRanks.WARN)) this._log(LogLevels.WARN, msg, args); } error(msg: string | number, args?: any[]) { - this._log(LogLevels.ERROR, msg, args); + if (this._shouldLog(logLevelRanks.ERROR)) this._log(LogLevels.ERROR, msg, args); } - private _log(level: LogLevel, msg: string | number, args?: any[]) { - if (this._shouldLog(level)) { - if (typeof msg === 'number') { - const format = this.codes.get(msg); - if (format) msg = sprintf(format, args); - else msg = `Message code ${msg}${args ? ', with args: ' + args.toString() : ''}`; - } - const formattedText = this._generateLogMessage(level, msg); - - console.log(formattedText); + _log(level: LogLevel, msg: string | number, args?: any[]) { + if (typeof msg === 'number') { + const format = this.codes.get(msg); + if (format) msg = sprintf(format, args); + else msg = `Message code ${msg}${args ? ', with args: ' + args.toString() : ''}`; } + const formattedText = this._generateLogMessage(level, msg); + + console.log(formattedText); } private _generateLogMessage(level: LogLevel, text: string) { @@ -81,19 +89,14 @@ export class Logger implements ILogger { result += '[' + level + ']' + (level === LogLevels.INFO || level === LogLevels.WARN ? ' ' : '') + ' '; } - if (this.category) { - result += this.category + textPre; + if (this.options.prefix) { + result += this.options.prefix + textPre; } return result += text; } - private _shouldLog(level: LogLevel) { - const logLevel = this.options.logLevel; - const levels = Object.keys(LogLevels).map((f) => LogLevels[f as keyof typeof LogLevels]); - const index = levels.indexOf(level); // What's the index of what it's trying to check if it should log - const levelIdx = levels.indexOf(logLevel); // What's the current log level index. - - return index >= levelIdx; + private _shouldLog(level: number) { + return level >= this.logLevel; } } diff --git a/src/logger/types.ts b/src/logger/types.ts index d691d255..4cacdba8 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -1,6 +1,7 @@ import { LogLevel } from '../types'; export interface ILoggerOptions { + prefix?: string, logLevel?: LogLevel, showLevel?: boolean, } diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index 2ef50b97..d1d65b27 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -63,7 +63,7 @@ export function validateLogger(settings: { debug: unknown }): ILogger { const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; - const log = new Logger('splitio', { logLevel: settingLogLevel || initialLogLevel }, allCodes); + const log = new Logger({ logLevel: settingLogLevel || initialLogLevel }, allCodes); // logs error if the provided settings debug value is invalid if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index 2a644618..e5fa4f90 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -1,4 +1,4 @@ -import { Logger } from '../../../logger'; +import { Logger, LogLevels } from '../../../logger'; import { ILogger } from '../../../logger/types'; function isLogger(log: any): log is ILogger { @@ -13,15 +13,15 @@ function isLogger(log: any): log is ILogger { */ export function validateLogger(settings: { debug: unknown }): ILogger { const { debug } = settings; - const log = new Logger('splitio', { logLevel: 'NONE' }); + const log = new Logger(); // @TODO support boolean and string values? if (!debug) return log; if (isLogger(debug)) return debug; - // logs error, for consistency with builtin logger validator - log.error('The provided `debug` value at config is invalid.'); + // logs error for consistency with builtin logger validator + log._log(LogLevels.ERROR, 'The provided `debug` value at config is invalid.'); return log; } From 8758d56f7c4ec6c9a0d6a8e426959492596a7ee0 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 19 Mar 2021 17:10:56 -0300 Subject: [PATCH 45/58] logger validator UTs --- .../logger/__tests__/index.spec.ts | 61 +++++++++++++++++++ .../logger/builtinLogger.ts | 30 +++------ .../settingsValidation/logger/commons.ts | 24 ++++++++ .../logger/pluggableLogger.ts | 26 +++++--- 4 files changed, 110 insertions(+), 31 deletions(-) create mode 100644 src/utils/settingsValidation/logger/__tests__/index.spec.ts create mode 100644 src/utils/settingsValidation/logger/commons.ts diff --git a/src/utils/settingsValidation/logger/__tests__/index.spec.ts b/src/utils/settingsValidation/logger/__tests__/index.spec.ts new file mode 100644 index 00000000..158b5c10 --- /dev/null +++ b/src/utils/settingsValidation/logger/__tests__/index.spec.ts @@ -0,0 +1,61 @@ +import { ILogger } from '../../../../logger/types'; +import { LogLevel } from '../../../../types'; +import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; + +import { validateLogger as pluggableValidateLogger } from '../pluggableLogger'; +import { validateLogger as builtinValidateLogger } from '../builtinLogger'; + +const testTargets = [ + [pluggableValidateLogger], + [builtinValidateLogger] +]; + +function getLogLevel(logger?: ILogger): LogLevel | undefined { // @ts-ignore + if (logger) return logger.options.logLevel; +} + +describe('logger validators', () => { + + const consoleLogSpy = jest.spyOn(global.console, 'log'); + afterEach(() => { consoleLogSpy.mockClear(); }); + + test.each(testTargets)('returns a NONE logger if `debug` property is not defined or false', (validateLogger) => { // @ts-ignore + expect(getLogLevel(validateLogger({}))).toBe('NONE'); + expect(getLogLevel(validateLogger({ debug: undefined }))).toBe('NONE'); + expect(getLogLevel(validateLogger({ debug: false }))).toBe('NONE'); + + expect(consoleLogSpy).not.toBeCalled(); + }); + + test.each(testTargets)('returns a NONE logger if `debug` property is invalid and logs the error', (validateLogger) => { + expect(getLogLevel(validateLogger({ debug: null }))).toBe('NONE'); + expect(getLogLevel(validateLogger({ debug: 10 }))).toBe('NONE'); + expect(getLogLevel(validateLogger({ debug: {} }))).toBe('NONE'); + + expect(consoleLogSpy).toBeCalledTimes(3); + }); + + test.each(testTargets)('returns a logger with the provided log level if `debug` property is true or a string log level', (validateLogger) => { + expect(getLogLevel(validateLogger({ debug: true }))).toBe('DEBUG'); + expect(getLogLevel(validateLogger({ debug: 'DEBUG' }))).toBe('DEBUG'); + expect(getLogLevel(validateLogger({ debug: 'INFO' }))).toBe('INFO'); + expect(getLogLevel(validateLogger({ debug: 'WARN' }))).toBe('WARN'); + expect(getLogLevel(validateLogger({ debug: 'ERROR' }))).toBe('ERROR'); + expect(getLogLevel(validateLogger({ debug: 'NONE' }))).toBe('NONE'); + + expect(consoleLogSpy).not.toBeCalled(); + }); + + test('pluggable logger validators / returns the provided logger at `debug` property if it is valid', () => { + expect(pluggableValidateLogger({ debug: loggerMock })).toBe(loggerMock); + + expect(consoleLogSpy).not.toBeCalled(); + }); + + test('builtin logger validators / returns a NONE logger if `debug` property is invalid and logs the error', () => { + expect(getLogLevel(builtinValidateLogger({ debug: loggerMock }))).toBe('NONE'); + + expect(consoleLogSpy).toBeCalledTimes(1); + }); + +}); diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index d1d65b27..86eaa824 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -1,6 +1,5 @@ import { isLogLevelString, Logger, LogLevels } from '../../../logger'; import { ILogger } from '../../../logger/types'; -import { LogLevel } from '../../../types'; import { isLocalStorageAvailable } from '../../env/isLocalStorageAvailable'; import { isNode } from '../../env/isNode'; import { codesError } from '../../../logger/messages/error'; @@ -8,6 +7,8 @@ import { codesWarn } from '../../../logger/messages/warn'; import { codesInfo } from '../../../logger/messages/info'; import { codesDebug } from '../../../logger/messages/debug'; import { _Map } from '../../lang/maps'; +import { getLogLevel } from './commons'; +import { LogLevel } from '../../../types'; const allCodes = new _Map(codesError.concat(codesWarn, codesInfo, codesDebug)); @@ -37,36 +38,21 @@ if (/^(enabled?|on)/i.test(initialState)) { initialLogLevel = initialState; } -// returns the LogLevel for the given debugValue or undefined if it is invalid. -// debugValue must be a boolean or LogLevel string. -export function getLogLevel(debugValue: unknown): LogLevel | undefined { - if (typeof debugValue === 'boolean') { - if (debugValue) { - return LogLevels.DEBUG; - } else { - return LogLevels.NONE; - } - } else if (typeof debugValue === 'string' && isLogLevelString(debugValue)) { - return debugValue; - } else { - return undefined; - } -} - /** * Validates the `debug` property at config and use it to set the log level. * - * @param settings user config object + * @param settings user config object, with an optional `debug` property of type boolean or string log level. * @returns a logger instance with the log level at `settings.debug`. If `settings.debug` is invalid or not provided, `initialLogLevel` is used. */ export function validateLogger(settings: { debug: unknown }): ILogger { + const { debug } = settings; - const settingLogLevel = settings.debug ? getLogLevel(settings.debug) : initialLogLevel; + const logLevel: LogLevel | undefined = debug !== undefined ? getLogLevel(debug) : initialLogLevel; - const log = new Logger({ logLevel: settingLogLevel || initialLogLevel }, allCodes); + const log = new Logger({ logLevel: logLevel || initialLogLevel }, allCodes); - // logs error if the provided settings debug value is invalid - if (!settingLogLevel) log.error('Invalid Log Level - No changes to the logs will be applied.'); + // if logLevel is undefined at this point, it means that settings `debug` value is invalid + if (!logLevel) log._log(LogLevels.ERROR, 'Invalid Log Level - No changes to the logs will be applied.'); return log; } diff --git a/src/utils/settingsValidation/logger/commons.ts b/src/utils/settingsValidation/logger/commons.ts new file mode 100644 index 00000000..ed7e2f54 --- /dev/null +++ b/src/utils/settingsValidation/logger/commons.ts @@ -0,0 +1,24 @@ + +import { LogLevels, isLogLevelString } from '../../../logger'; +import { LogLevel } from '../../../types'; + +/** + * Returns the LogLevel for the given debugValue or undefined if it is invalid, + * i.e., if the debugValue is not a boolean or LogLevel string. + * + * @param debugValue debug value at config + * @returns LogLevel of the given debugValue + */ +export function getLogLevel(debugValue: unknown): LogLevel | undefined { + if (typeof debugValue === 'boolean') { + if (debugValue) { + return LogLevels.DEBUG; + } else { + return LogLevels.NONE; + } + } else if (typeof debugValue === 'string' && isLogLevelString(debugValue)) { + return debugValue; + } else { + return undefined; + } +} diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index e5fa4f90..d93a6cc4 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -1,27 +1,35 @@ import { Logger, LogLevels } from '../../../logger'; import { ILogger } from '../../../logger/types'; +import { LogLevel } from '../../../types'; +import { getLogLevel } from './commons'; function isLogger(log: any): log is ILogger { return log && typeof log.debug === 'function' && typeof log.info === 'function' && typeof log.warn === 'function' && typeof log.error === 'function' && typeof log.setLogLevel === 'function'; } +// By default it starts disabled. +let initialLogLevel = LogLevels.NONE; + /** - * Validates the `debug` (logger) property at config. + * Validates the `debug` property at config and use it to set the logger. * - * @param settings user config object - * @returns the provided logger at `settings.debug` or a new one with NONE log level if the provided one is invalid + * @param settings user config object, with an optional `debug` property of type boolean, string log level or a Logger object. + * @returns a logger instance, that might be: the provided logger at `settings.debug`, or one with the given `debug` log level, + * or one with NONE log level if `debug` is not defined or invalid. */ export function validateLogger(settings: { debug: unknown }): ILogger { const { debug } = settings; - const log = new Logger(); + let logLevel: LogLevel | undefined = initialLogLevel; - // @TODO support boolean and string values? - if (!debug) return log; + if (debug !== undefined) { + if (isLogger(debug)) return debug; + logLevel = getLogLevel(settings.debug); + } - if (isLogger(debug)) return debug; + const log = new Logger({ logLevel: logLevel || initialLogLevel }); - // logs error for consistency with builtin logger validator - log._log(LogLevels.ERROR, 'The provided `debug` value at config is invalid.'); + // if logLevel is undefined at this point, it means that `debug` value is invalid + if (!logLevel) log._log(LogLevels.ERROR, 'Invalid `debug` value at config. Logs will be disabled.'); return log; } From 7c52907bb1dc0fa8357ae81c45b8a168ef17a17e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 19 Mar 2021 18:04:13 -0300 Subject: [PATCH 46/58] added UTs --- src/logger/__tests__/index.spec.ts | 27 ++++++++++++--- src/logger/__tests__/sdkLogger.mock.ts | 5 +++ src/logger/__tests__/sdkLogger.spec.ts | 17 +++++----- src/logger/index.ts | 5 +-- .../logger/__tests__/index.spec.ts | 34 ++++++++----------- 5 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index 3a08510d..82f5c16b 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -1,5 +1,6 @@ import { LogLevel } from '../../types'; -import { Logger, LogLevels, isLogLevelString } from '../index'; +import { _Map } from '../../utils/lang/maps'; +import { Logger, LogLevels, isLogLevelString, _sprintf } from '../index'; // We'll set this only once. These are the constants we will use for // comparing the LogLevel values. @@ -52,12 +53,13 @@ function testLogLevels(levelToTest: LogLevel) { const consoleLogSpy = jest.spyOn(global.console, 'log'); // Runs the suite with the given value for showLevel option. - const runTests = (showLevel?: boolean) => { + const runTests = (showLevel?: boolean, useCodes?: boolean) => { let logLevelLogsCounter = 0; let testForNoLog = false; const logMethod = levelToTest.toLowerCase(); const logCategory = `test-category-${logMethod}`; - const instance = new Logger({ prefix: logCategory, showLevel }); + const instance = new Logger({ prefix: logCategory, showLevel }, + useCodes ? new _Map([[1, 'Test log for level %s with showLevel: %s %s']]) : undefined); LOG_LEVELS_IN_ORDER.forEach((logLevel, i) => { const logMsg = `Test log for level ${levelToTest} with showLevel: ${showLevel} ${logLevelLogsCounter}`; @@ -67,7 +69,8 @@ function testLogLevels(levelToTest: LogLevel) { instance.setLogLevel(LogLevels[logLevel]); // Call the method // @ts-ignore - instance[logMethod](logMsg); + if (useCodes) instance[logMethod](1, [levelToTest, showLevel, logLevelLogsCounter]); // @ts-ignore + else instance[logMethod](logMsg); // Assert if console.log was called. const actualMessage = consoleLogSpy.mock.calls[consoleLogSpy.mock.calls.length - 1][0]; if (testForNoLog) { @@ -87,6 +90,8 @@ function testLogLevels(levelToTest: LogLevel) { runTests(true); // Hide logLevel runTests(false); + // Hide logLevel and use message codes + runTests(false, true); // Restore spied object. consoleLogSpy.mockRestore(); @@ -112,3 +117,17 @@ test('SPLIT LOGGER / Logger class public methods behaviour - instance.error', () testLogLevels(LogLevels.ERROR); }); + +test('_sprintf', () => { + expect(_sprintf()).toBe(''); + expect(_sprintf(undefined, [/regex/, 'arg', 10, {}])).toBe(''); + + expect(_sprintf('text')).toBe('text'); + expect(_sprintf('text', [])).toBe('text'); + expect(_sprintf('text', [/regex/, 'arg', 10, {}])).toBe('text'); + + expect(_sprintf('text %s', [])).toBe('text undefined'); + expect(_sprintf('text %s', ['arg1'])).toBe('text arg1'); + expect(_sprintf('text %s', ['arg1', 'arg2'])).toBe('text arg1'); + expect(_sprintf('%s text %s', ['arg1', true, 'arg3'])).toBe('arg1 text true'); +}); diff --git a/src/logger/__tests__/sdkLogger.mock.ts b/src/logger/__tests__/sdkLogger.mock.ts index f7af2c62..a2cc184f 100644 --- a/src/logger/__tests__/sdkLogger.mock.ts +++ b/src/logger/__tests__/sdkLogger.mock.ts @@ -1,3 +1,4 @@ +import { LogLevel } from '../../types'; export const loggerMock = { warn: jest.fn(), @@ -14,3 +15,7 @@ export const loggerMock = { this.setLogLevel.mockClear(); } }; + +export function getLoggerLogLevel(logger: any): LogLevel | undefined { + if (logger) return logger.options.logLevel; +} diff --git a/src/logger/__tests__/sdkLogger.spec.ts b/src/logger/__tests__/sdkLogger.spec.ts index 6fc87787..a69a587c 100644 --- a/src/logger/__tests__/sdkLogger.spec.ts +++ b/src/logger/__tests__/sdkLogger.spec.ts @@ -1,5 +1,6 @@ import { createLoggerAPI } from '../sdkLogger'; import { Logger, LogLevels } from '../index'; +import { getLoggerLogLevel } from './sdkLogger.mock'; test('LoggerAPI / methods and props', () => { // creates a LoggerAPI instance @@ -9,19 +10,19 @@ test('LoggerAPI / methods and props', () => { expect(typeof API).toBe('object'); // Our logger should expose an API object. expect(typeof API.setLogLevel).toBe('function'); // API object should have setLogLevel method. - API.setLogLevel('INFO'); // @ts-ignore, accessing private prop - expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel should update the log level. + API.setLogLevel('INFO'); + expect(getLoggerLogLevel(logger)).toBe('INFO'); // calling setLogLevel should update the log level. // @ts-ignore, passing wrong type - API.setLogLevel('warn'); // @ts-ignore, accessing private prop - expect(logger.options.logLevel).toBe('INFO'); // calling setLogLevel with an invalid value should not update the log level. + API.setLogLevel('warn'); + expect(getLoggerLogLevel(logger)).toBe('INFO'); // calling setLogLevel with an invalid value should not update the log level. expect(typeof API.enable).toBe('function'); // API object should have enable method. - API.enable(); // @ts-ignore, accessing private prop - expect(logger.options.logLevel).toBe('DEBUG'); // calling enable should update logger log level to DEBUG. + API.enable(); + expect(getLoggerLogLevel(logger)).toBe('DEBUG'); // calling enable should update logger log level to DEBUG. expect(typeof API.disable).toBe('function'); // API object should have disable method. - API.disable(); // @ts-ignore, accessing private prop - expect(logger.options.logLevel).toBe('NONE'); // calling disable should update logger log level to NONE. + API.disable(); + expect(getLoggerLogLevel(logger)).toBe('NONE'); // calling disable should update logger log level to NONE. expect(API.LogLevel).toEqual(LogLevels); // API object should have LogLevel prop including all available levels. diff --git a/src/logger/index.ts b/src/logger/index.ts index afb3b8ac..6989c808 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -24,7 +24,8 @@ export function isLogLevelString(str: string): str is LogLevel { return !!find(LogLevels, (lvl: string) => str === lvl); } -function sprintf(format: string = '', args: any[] = []): string { +// exported for testing purposes only +export function _sprintf(format: string = '', args: any[] = []): string { var i = 0; return format.replace(/%s/g, function () { return args[i++]; @@ -73,7 +74,7 @@ export class Logger implements ILogger { _log(level: LogLevel, msg: string | number, args?: any[]) { if (typeof msg === 'number') { const format = this.codes.get(msg); - if (format) msg = sprintf(format, args); + if (format) msg = _sprintf(format, args); else msg = `Message code ${msg}${args ? ', with args: ' + args.toString() : ''}`; } const formattedText = this._generateLogMessage(level, msg); diff --git a/src/utils/settingsValidation/logger/__tests__/index.spec.ts b/src/utils/settingsValidation/logger/__tests__/index.spec.ts index 158b5c10..2aee9882 100644 --- a/src/utils/settingsValidation/logger/__tests__/index.spec.ts +++ b/src/utils/settingsValidation/logger/__tests__/index.spec.ts @@ -1,6 +1,4 @@ -import { ILogger } from '../../../../logger/types'; -import { LogLevel } from '../../../../types'; -import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock'; +import { loggerMock, getLoggerLogLevel } from '../../../../logger/__tests__/sdkLogger.mock'; import { validateLogger as pluggableValidateLogger } from '../pluggableLogger'; import { validateLogger as builtinValidateLogger } from '../builtinLogger'; @@ -10,38 +8,34 @@ const testTargets = [ [builtinValidateLogger] ]; -function getLogLevel(logger?: ILogger): LogLevel | undefined { // @ts-ignore - if (logger) return logger.options.logLevel; -} - describe('logger validators', () => { const consoleLogSpy = jest.spyOn(global.console, 'log'); afterEach(() => { consoleLogSpy.mockClear(); }); test.each(testTargets)('returns a NONE logger if `debug` property is not defined or false', (validateLogger) => { // @ts-ignore - expect(getLogLevel(validateLogger({}))).toBe('NONE'); - expect(getLogLevel(validateLogger({ debug: undefined }))).toBe('NONE'); - expect(getLogLevel(validateLogger({ debug: false }))).toBe('NONE'); + expect(getLoggerLogLevel(validateLogger({}))).toBe('NONE'); + expect(getLoggerLogLevel(validateLogger({ debug: undefined }))).toBe('NONE'); + expect(getLoggerLogLevel(validateLogger({ debug: false }))).toBe('NONE'); expect(consoleLogSpy).not.toBeCalled(); }); test.each(testTargets)('returns a NONE logger if `debug` property is invalid and logs the error', (validateLogger) => { - expect(getLogLevel(validateLogger({ debug: null }))).toBe('NONE'); - expect(getLogLevel(validateLogger({ debug: 10 }))).toBe('NONE'); - expect(getLogLevel(validateLogger({ debug: {} }))).toBe('NONE'); + expect(getLoggerLogLevel(validateLogger({ debug: null }))).toBe('NONE'); + expect(getLoggerLogLevel(validateLogger({ debug: 10 }))).toBe('NONE'); + expect(getLoggerLogLevel(validateLogger({ debug: {} }))).toBe('NONE'); expect(consoleLogSpy).toBeCalledTimes(3); }); test.each(testTargets)('returns a logger with the provided log level if `debug` property is true or a string log level', (validateLogger) => { - expect(getLogLevel(validateLogger({ debug: true }))).toBe('DEBUG'); - expect(getLogLevel(validateLogger({ debug: 'DEBUG' }))).toBe('DEBUG'); - expect(getLogLevel(validateLogger({ debug: 'INFO' }))).toBe('INFO'); - expect(getLogLevel(validateLogger({ debug: 'WARN' }))).toBe('WARN'); - expect(getLogLevel(validateLogger({ debug: 'ERROR' }))).toBe('ERROR'); - expect(getLogLevel(validateLogger({ debug: 'NONE' }))).toBe('NONE'); + expect(getLoggerLogLevel(validateLogger({ debug: true }))).toBe('DEBUG'); + expect(getLoggerLogLevel(validateLogger({ debug: 'DEBUG' }))).toBe('DEBUG'); + expect(getLoggerLogLevel(validateLogger({ debug: 'INFO' }))).toBe('INFO'); + expect(getLoggerLogLevel(validateLogger({ debug: 'WARN' }))).toBe('WARN'); + expect(getLoggerLogLevel(validateLogger({ debug: 'ERROR' }))).toBe('ERROR'); + expect(getLoggerLogLevel(validateLogger({ debug: 'NONE' }))).toBe('NONE'); expect(consoleLogSpy).not.toBeCalled(); }); @@ -53,7 +47,7 @@ describe('logger validators', () => { }); test('builtin logger validators / returns a NONE logger if `debug` property is invalid and logs the error', () => { - expect(getLogLevel(builtinValidateLogger({ debug: loggerMock }))).toBe('NONE'); + expect(getLoggerLogLevel(builtinValidateLogger({ debug: loggerMock }))).toBe('NONE'); expect(consoleLogSpy).toBeCalledTimes(1); }); From ba357d6455ca5d99a0ab530f11c9172d7662338c Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 19 Mar 2021 19:26:30 -0300 Subject: [PATCH 47/58] refactor Logger functions --- .../{debugLogger.ts => DebugLogger.ts} | 7 +++---- .../{errorLogger.ts => ErrorLogger.ts} | 7 +++---- .../browser/{infoLogger.ts => InfoLogger.ts} | 7 +++---- .../browser/{warnLogger.ts => WarnLogger.ts} | 7 +++---- src/logger/browser/__tests__/index.spec.ts | 21 +++++++++++++++++++ 5 files changed, 33 insertions(+), 16 deletions(-) rename src/logger/browser/{debugLogger.ts => DebugLogger.ts} (65%) rename src/logger/browser/{errorLogger.ts => ErrorLogger.ts} (56%) rename src/logger/browser/{infoLogger.ts => InfoLogger.ts} (63%) rename src/logger/browser/{warnLogger.ts => WarnLogger.ts} (60%) create mode 100644 src/logger/browser/__tests__/index.spec.ts diff --git a/src/logger/browser/debugLogger.ts b/src/logger/browser/DebugLogger.ts similarity index 65% rename from src/logger/browser/debugLogger.ts rename to src/logger/browser/DebugLogger.ts index d1a2aee8..774c1600 100644 --- a/src/logger/browser/debugLogger.ts +++ b/src/logger/browser/DebugLogger.ts @@ -5,7 +5,6 @@ import { codesInfo } from '../messages/info'; import { codesDebug } from '../messages/debug'; import { _Map } from '../../utils/lang/maps'; -export const debugLogger = new Logger( - { logLevel: 'DEBUG' }, - new _Map(codesError.concat(codesWarn, codesInfo, codesDebug)) -); +export function DebugLogger() { + return new Logger({ logLevel: 'DEBUG' }, new _Map(codesError.concat(codesWarn, codesInfo, codesDebug))); +} diff --git a/src/logger/browser/errorLogger.ts b/src/logger/browser/ErrorLogger.ts similarity index 56% rename from src/logger/browser/errorLogger.ts rename to src/logger/browser/ErrorLogger.ts index 33aaa4a5..f0702d89 100644 --- a/src/logger/browser/errorLogger.ts +++ b/src/logger/browser/ErrorLogger.ts @@ -2,7 +2,6 @@ import { Logger } from '../index'; import { codesError } from '../messages/error'; import { _Map } from '../../utils/lang/maps'; -export const errorLogger = new Logger( - { logLevel: 'ERROR' }, - new _Map(codesError) -); +export function ErrorLogger() { + return new Logger({ logLevel: 'ERROR' }, new _Map(codesError)); +} diff --git a/src/logger/browser/infoLogger.ts b/src/logger/browser/InfoLogger.ts similarity index 63% rename from src/logger/browser/infoLogger.ts rename to src/logger/browser/InfoLogger.ts index 70eada90..e38f41b8 100644 --- a/src/logger/browser/infoLogger.ts +++ b/src/logger/browser/InfoLogger.ts @@ -4,7 +4,6 @@ import { codesWarn } from '../messages/warn'; import { codesInfo } from '../messages/info'; import { _Map } from '../../utils/lang/maps'; -export const infoLogger = new Logger( - { logLevel: 'INFO' }, - new _Map(codesError.concat(codesWarn, codesInfo)) -); +export function InfoLogger() { + return new Logger({ logLevel: 'INFO' }, new _Map(codesError.concat(codesWarn, codesInfo))); +} diff --git a/src/logger/browser/warnLogger.ts b/src/logger/browser/WarnLogger.ts similarity index 60% rename from src/logger/browser/warnLogger.ts rename to src/logger/browser/WarnLogger.ts index 5af9440c..6f6747b0 100644 --- a/src/logger/browser/warnLogger.ts +++ b/src/logger/browser/WarnLogger.ts @@ -3,7 +3,6 @@ import { codesError } from '../messages/error'; import { codesWarn } from '../messages/warn'; import { _Map } from '../../utils/lang/maps'; -export const warnLogger = new Logger( - { logLevel: 'WARN' }, - new _Map(codesError.concat(codesWarn)) -); +export function WarnLogger() { + return new Logger({ logLevel: 'WARN' }, new _Map(codesError.concat(codesWarn))); +} diff --git a/src/logger/browser/__tests__/index.spec.ts b/src/logger/browser/__tests__/index.spec.ts new file mode 100644 index 00000000..178c6a59 --- /dev/null +++ b/src/logger/browser/__tests__/index.spec.ts @@ -0,0 +1,21 @@ +import { getLoggerLogLevel } from '../../__tests__/sdkLogger.mock'; +import { DebugLogger } from '../DebugLogger'; +import { InfoLogger } from '../InfoLogger'; +import { WarnLogger } from '../WarnLogger'; +import { ErrorLogger } from '../ErrorLogger'; + +test('DebugLogger', () => { + expect(getLoggerLogLevel(DebugLogger())).toBe('DEBUG'); +}); + +test('InfoLogger', () => { + expect(getLoggerLogLevel(InfoLogger())).toBe('INFO'); +}); + +test('WarnLogger', () => { + expect(getLoggerLogLevel(WarnLogger())).toBe('WARN'); +}); + +test('ErrorLogger', () => { + expect(getLoggerLogLevel(ErrorLogger())).toBe('ERROR'); +}); From 82f41b517ae9e33d17b61282d48c640d93549561 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 22 Mar 2021 17:36:00 -0300 Subject: [PATCH 48/58] fix: using prefix in error logs related to invalid api key --- src/logger/constants.ts | 1 + src/sync/polling/syncTasks/segmentsSyncTask.ts | 4 ++-- src/utils/inputValidation/apiKey.ts | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 2855ae13..775577be 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -122,6 +122,7 @@ export const WARN_API_KEY = 226; // Log prefixes/tags/categories export const SETTINGS_LB = 'settings'; +export const INSTANTIATION_LB = 'Factory instantiation'; export const ENGINE_LB = 'engine'; export const ENGINE_COMBINER_LB = ENGINE_LB + ':combiner: '; export const ENGINE_MATCHER_LB = ENGINE_LB + ':matcher: '; diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index 359a5620..bf131d5c 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -11,7 +11,7 @@ import { IFetchSegmentChanges } from '../../../services/types'; import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; -import { SETTINGS_LB, SYNC_SEGMENTS_LB } from '../../../logger/constants'; +import { INSTANTIATION_LB, SYNC_SEGMENTS_LB } from '../../../logger/constants'; type ISegmentChangesUpdater = (segmentNames?: string[], noCache?: boolean, fetchOnlyNew?: boolean) => Promise @@ -97,7 +97,7 @@ function segmentChangesUpdaterFactory( if (error.statusCode === 403) { // @TODO although factory status is destroyed, synchronization is not stopped readiness.destroy(); - log.error(SETTINGS_LB + 'you passed a client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.'); + log.error(INSTANTIATION_LB + ': you passed a client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.'); } return false; diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index c4e3d2ff..a629815a 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -1,4 +1,4 @@ -import { ERROR_NULL, ERROR_EMPTY, ERROR_INVALID, WARN_API_KEY, SETTINGS_LB } from '../../logger/constants'; +import { ERROR_NULL, ERROR_EMPTY, ERROR_INVALID, WARN_API_KEY, INSTANTIATION_LB } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; @@ -8,14 +8,14 @@ const item = 'api_key'; export function validateApiKey(log: ILogger, maybeApiKey: any): string | false { let apiKey: string | false = false; if (maybeApiKey == undefined) { // eslint-disable-line eqeqeq - log.error(ERROR_NULL, [SETTINGS_LB, item]); + log.error(ERROR_NULL, [INSTANTIATION_LB, item]); } else if (isString(maybeApiKey)) { if (maybeApiKey.length > 0) apiKey = maybeApiKey; else - log.error(ERROR_EMPTY, [SETTINGS_LB, item]); + log.error(ERROR_EMPTY, [INSTANTIATION_LB, item]); } else { - log.error(ERROR_INVALID, [SETTINGS_LB, item]); + log.error(ERROR_INVALID, [INSTANTIATION_LB, item]); } return apiKey; From 6598744f1bf3774b2183392b976a2deccde7515e Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 23 Mar 2021 11:25:12 -0300 Subject: [PATCH 49/58] feedback --- src/logger/__tests__/index.spec.ts | 2 +- src/logger/index.ts | 24 ++++++++++--------- .../logger/__tests__/index.spec.ts | 14 +++++------ .../logger/builtinLogger.ts | 2 +- .../settingsValidation/logger/commons.ts | 2 +- .../logger/pluggableLogger.ts | 2 +- 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/logger/__tests__/index.spec.ts b/src/logger/__tests__/index.spec.ts index 82f5c16b..93085c25 100644 --- a/src/logger/__tests__/index.spec.ts +++ b/src/logger/__tests__/index.spec.ts @@ -118,7 +118,7 @@ test('SPLIT LOGGER / Logger class public methods behaviour - instance.error', () }); -test('_sprintf', () => { +test('SPLIT LOGGER / _sprintf', () => { expect(_sprintf()).toBe(''); expect(_sprintf(undefined, [/regex/, 'arg', 10, {}])).toBe(''); diff --git a/src/logger/index.ts b/src/logger/index.ts index 6989c808..4738e191 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -12,7 +12,7 @@ export const LogLevels: { [level: string]: LogLevel } = { NONE: 'NONE' }; -const logLevelRanks = { +const LogLevelRanks = { DEBUG: 1, INFO: 2, WARN: 3, @@ -26,7 +26,7 @@ export function isLogLevelString(str: string): str is LogLevel { // exported for testing purposes only export function _sprintf(format: string = '', args: any[] = []): string { - var i = 0; + let i = 0; return format.replace(/%s/g, function () { return args[i++]; }); @@ -47,36 +47,38 @@ export class Logger implements ILogger { constructor(options?: ILoggerOptions, codes?: IMap) { this.options = objectAssign({}, defaultOptions, options); this.codes = codes || new _Map(); - this.logLevel = logLevelRanks[this.options.logLevel]; + this.logLevel = LogLevelRanks[this.options.logLevel]; } setLogLevel(logLevel: LogLevel) { this.options.logLevel = logLevel; - this.logLevel = logLevelRanks[logLevel]; + this.logLevel = LogLevelRanks[logLevel]; } debug(msg: string | number, args?: any[]) { - if (this._shouldLog(logLevelRanks.DEBUG)) this._log(LogLevels.DEBUG, msg, args); + if (this._shouldLog(LogLevelRanks.DEBUG)) this._log(LogLevels.DEBUG, msg, args); } info(msg: string | number, args?: any[]) { - if (this._shouldLog(logLevelRanks.INFO)) this._log(LogLevels.INFO, msg, args); + if (this._shouldLog(LogLevelRanks.INFO)) this._log(LogLevels.INFO, msg, args); } warn(msg: string | number, args?: any[]) { - if (this._shouldLog(logLevelRanks.WARN)) this._log(LogLevels.WARN, msg, args); + if (this._shouldLog(LogLevelRanks.WARN)) this._log(LogLevels.WARN, msg, args); } error(msg: string | number, args?: any[]) { - if (this._shouldLog(logLevelRanks.ERROR)) this._log(LogLevels.ERROR, msg, args); + if (this._shouldLog(LogLevelRanks.ERROR)) this._log(LogLevels.ERROR, msg, args); } - _log(level: LogLevel, msg: string | number, args?: any[]) { + private _log(level: LogLevel, msg: string | number, args?: any[]) { if (typeof msg === 'number') { const format = this.codes.get(msg); - if (format) msg = _sprintf(format, args); - else msg = `Message code ${msg}${args ? ', with args: ' + args.toString() : ''}`; + msg = format ? _sprintf(format, args) : `Message code ${msg}${args ? ', with args: ' + args.toString() : ''}`; + } else { + if (args) msg = _sprintf(msg, args); } + const formattedText = this._generateLogMessage(level, msg); console.log(formattedText); diff --git a/src/utils/settingsValidation/logger/__tests__/index.spec.ts b/src/utils/settingsValidation/logger/__tests__/index.spec.ts index 2aee9882..3f91c2db 100644 --- a/src/utils/settingsValidation/logger/__tests__/index.spec.ts +++ b/src/utils/settingsValidation/logger/__tests__/index.spec.ts @@ -26,7 +26,13 @@ describe('logger validators', () => { expect(getLoggerLogLevel(validateLogger({ debug: 10 }))).toBe('NONE'); expect(getLoggerLogLevel(validateLogger({ debug: {} }))).toBe('NONE'); - expect(consoleLogSpy).toBeCalledTimes(3); + if (validateLogger === builtinValidateLogger) { + // for builtinValidateLogger, a logger cannot be passed as `debug` property + expect(getLoggerLogLevel(validateLogger({ debug: loggerMock }))).toBe('NONE'); + expect(consoleLogSpy).toBeCalledTimes(4); + } else { + expect(consoleLogSpy).toBeCalledTimes(3); + } }); test.each(testTargets)('returns a logger with the provided log level if `debug` property is true or a string log level', (validateLogger) => { @@ -46,10 +52,4 @@ describe('logger validators', () => { expect(consoleLogSpy).not.toBeCalled(); }); - test('builtin logger validators / returns a NONE logger if `debug` property is invalid and logs the error', () => { - expect(getLoggerLogLevel(builtinValidateLogger({ debug: loggerMock }))).toBe('NONE'); - - expect(consoleLogSpy).toBeCalledTimes(1); - }); - }); diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index 86eaa824..9c314a7c 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -51,7 +51,7 @@ export function validateLogger(settings: { debug: unknown }): ILogger { const log = new Logger({ logLevel: logLevel || initialLogLevel }, allCodes); - // if logLevel is undefined at this point, it means that settings `debug` value is invalid + // @ts-ignore // if logLevel is undefined at this point, it means that settings `debug` value is invalid if (!logLevel) log._log(LogLevels.ERROR, 'Invalid Log Level - No changes to the logs will be applied.'); return log; diff --git a/src/utils/settingsValidation/logger/commons.ts b/src/utils/settingsValidation/logger/commons.ts index ed7e2f54..a51ba991 100644 --- a/src/utils/settingsValidation/logger/commons.ts +++ b/src/utils/settingsValidation/logger/commons.ts @@ -7,7 +7,7 @@ import { LogLevel } from '../../../types'; * i.e., if the debugValue is not a boolean or LogLevel string. * * @param debugValue debug value at config - * @returns LogLevel of the given debugValue + * @returns LogLevel of the given debugValue or undefined if the provided value is invalid */ export function getLogLevel(debugValue: unknown): LogLevel | undefined { if (typeof debugValue === 'boolean') { diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index d93a6cc4..90746543 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -28,7 +28,7 @@ export function validateLogger(settings: { debug: unknown }): ILogger { const log = new Logger({ logLevel: logLevel || initialLogLevel }); - // if logLevel is undefined at this point, it means that `debug` value is invalid + // @ts-ignore // if logLevel is undefined at this point, it means that `debug` value is invalid if (!logLevel) log._log(LogLevels.ERROR, 'Invalid `debug` value at config. Logs will be disabled.'); return log; From c9f2943c7c3919de7e65da349f9a414363f6f74d Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 23 Mar 2021 13:01:18 -0300 Subject: [PATCH 50/58] polishing --- .nvmrc | 2 +- src/logger/browser/DebugLogger.ts | 5 +---- src/logger/browser/InfoLogger.ts | 4 +--- src/logger/browser/WarnLogger.ts | 3 +-- src/logger/messages/debug.ts | 5 +++-- src/logger/messages/info.ts | 5 +++-- src/logger/messages/warn.ts | 5 +++-- src/storages/inLocalStorage/MySegmentsCacheInLocal.ts | 4 +--- src/storages/inLocalStorage/SplitsCacheInLocal.ts | 2 +- src/storages/inLocalStorage/constants.ts | 2 ++ src/storages/inLocalStorage/index.ts | 3 +-- src/types.ts | 2 +- src/utils/murmur3/murmur3.ts | 2 +- src/utils/murmur3/murmur3_128.ts | 2 +- src/utils/settingsValidation/logger/builtinLogger.ts | 7 ++----- 15 files changed, 23 insertions(+), 30 deletions(-) create mode 100644 src/storages/inLocalStorage/constants.ts diff --git a/.nvmrc b/.nvmrc index a62187b7..958b5a36 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v10.16 +v14 diff --git a/src/logger/browser/DebugLogger.ts b/src/logger/browser/DebugLogger.ts index 774c1600..105e1890 100644 --- a/src/logger/browser/DebugLogger.ts +++ b/src/logger/browser/DebugLogger.ts @@ -1,10 +1,7 @@ import { Logger } from '../index'; -import { codesError } from '../messages/error'; -import { codesWarn } from '../messages/warn'; -import { codesInfo } from '../messages/info'; import { codesDebug } from '../messages/debug'; import { _Map } from '../../utils/lang/maps'; export function DebugLogger() { - return new Logger({ logLevel: 'DEBUG' }, new _Map(codesError.concat(codesWarn, codesInfo, codesDebug))); + return new Logger({ logLevel: 'DEBUG' }, new _Map(codesDebug)); } diff --git a/src/logger/browser/InfoLogger.ts b/src/logger/browser/InfoLogger.ts index e38f41b8..bdf9be75 100644 --- a/src/logger/browser/InfoLogger.ts +++ b/src/logger/browser/InfoLogger.ts @@ -1,9 +1,7 @@ import { Logger } from '../index'; -import { codesError } from '../messages/error'; -import { codesWarn } from '../messages/warn'; import { codesInfo } from '../messages/info'; import { _Map } from '../../utils/lang/maps'; export function InfoLogger() { - return new Logger({ logLevel: 'INFO' }, new _Map(codesError.concat(codesWarn, codesInfo))); + return new Logger({ logLevel: 'INFO' }, new _Map(codesInfo)); } diff --git a/src/logger/browser/WarnLogger.ts b/src/logger/browser/WarnLogger.ts index 6f6747b0..8456d012 100644 --- a/src/logger/browser/WarnLogger.ts +++ b/src/logger/browser/WarnLogger.ts @@ -1,8 +1,7 @@ import { Logger } from '../index'; -import { codesError } from '../messages/error'; import { codesWarn } from '../messages/warn'; import { _Map } from '../../utils/lang/maps'; export function WarnLogger() { - return new Logger({ logLevel: 'WARN' }, new _Map(codesError.concat(codesWarn))); + return new Logger({ logLevel: 'WARN' }, new _Map(codesWarn)); } diff --git a/src/logger/messages/debug.ts b/src/logger/messages/debug.ts index 714ff483..c39fef55 100644 --- a/src/logger/messages/debug.ts +++ b/src/logger/messages/debug.ts @@ -1,6 +1,7 @@ import { DEBUG_ENGINE_COMBINER_AND, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_SPLITS_FILTER, SETTINGS_LB, ENGINE_LB, ENGINE_COMBINER_LB, ENGINE_MATCHER_LB, ENGINE_VALUE_LB, SYNC_OFFLINE_LB, IMPRESSIONS_TRACKER_LB, SYNC_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, CLEANUP_LB, DEBUG_26, DEBUG_27 } from '../constants'; +import { codesInfo } from './info'; -export const codesDebug: [number, string][] = [ +export const codesDebug: [number, string][] = codesInfo.concat([ // evaluator [DEBUG_ENGINE_COMBINER_AND, ENGINE_COMBINER_LB + '[andCombiner] evaluates to %s'], [DEBUG_1, ENGINE_COMBINER_LB + 'Treatment found: %s'], @@ -46,4 +47,4 @@ export const codesDebug: [number, string][] = [ [DEBUG_50, IMPRESSIONS_TRACKER_LB + 'Successfully stored %s impression%s.'], // initialization / settings validation [DEBUG_SPLITS_FILTER, SETTINGS_LB + ': splits filtering criteria is "%s".'] -]; +]); diff --git a/src/logger/messages/info.ts b/src/logger/messages/info.ts index 665ca8d8..16f542c6 100644 --- a/src/logger/messages/info.ts +++ b/src/logger/messages/info.ts @@ -1,8 +1,9 @@ import { INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21, EVENTS_TRACKER_LB, SYNC_MANAGER_LB, SYNC_POLLING_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, SYNC_SUBMITTERS_LB, IMPRESSIONS_TRACKER_LB } from '../constants'; +import { codesWarn } from './warn'; const READY_MSG = 'Split SDK is ready'; -export const codesInfo: [number, string][] = [ +export const codesInfo: [number, string][] = codesWarn.concat([ // client status [INFO_CLIENT_READY_FROM_CACHE, READY_MSG + ' from cache'], [INFO_CLIENT_READY, READY_MSG], @@ -28,4 +29,4 @@ export const codesInfo: [number, string][] = [ [INFO_18, SYNC_MANAGER_LB + 'Streaming not available. Starting polling.'], [INFO_19, SYNC_MANAGER_LB + 'Streaming couldn\'t connect. Continue polling.'], [INFO_20, SYNC_MANAGER_LB + 'Streaming (re)connected. Syncing and stopping polling.'], -]; +]); diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index f351cd2d..c3338be4 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -1,6 +1,7 @@ import { WARN_ENGINE_INVALID_VALUE, WARN_ENGINE_NO_ATTRIBUTES, WARN_CLIENT_NO_LISTENER, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, WARN_CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, SETTINGS_LB, ENGINE_VALUE_LB, EVENTS_TRACKER_LB, SYNC_MYSEGMENTS_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, SYNC_SUBMITTERS_LB } from '../constants'; +import { codesError } from './error'; -export const codesWarn: [number, string][] = [ +export const codesWarn: [number, string][] = codesError.concat([ // evaluator [WARN_ENGINE_INVALID_VALUE, ENGINE_VALUE_LB + 'Value %s doesn\'t match with expected type.'], [WARN_ENGINE_NO_ATTRIBUTES, ENGINE_VALUE_LB + 'Defined attribute [%s], no attributes received.'], @@ -32,4 +33,4 @@ export const codesWarn: [number, string][] = [ [WARN_SPLITS_FILTER_EMPTY, SETTINGS_LB+': splitFilters configuration must be a non-empty array of filter objects.'], [WARN_STORAGE_INVALID, SETTINGS_LB+': The provided storage is invalid. Fallbacking into default MEMORY storage'], [WARN_API_KEY, SETTINGS_LB+': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'] -]; +]); diff --git a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts index cfa58b9f..020f823a 100644 --- a/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +++ b/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts @@ -1,9 +1,7 @@ import { ILogger } from '../../logger/types'; import AbstractSegmentsCacheSync from '../AbstractSegmentsCacheSync'; import KeyBuilderCS from '../KeyBuilderCS'; -import { logPrefix } from './index'; - -const DEFINED = '1'; +import { logPrefix, DEFINED } from './constants'; export default class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync { diff --git a/src/storages/inLocalStorage/SplitsCacheInLocal.ts b/src/storages/inLocalStorage/SplitsCacheInLocal.ts index 47ec5584..58d5ba09 100644 --- a/src/storages/inLocalStorage/SplitsCacheInLocal.ts +++ b/src/storages/inLocalStorage/SplitsCacheInLocal.ts @@ -3,7 +3,7 @@ import AbstractSplitsCacheSync, { usesSegments } from '../AbstractSplitsCacheSyn import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang'; import KeyBuilderCS from '../KeyBuilderCS'; import { ILogger } from '../../logger/types'; -import { logPrefix } from './index'; +import { logPrefix } from './constants'; /** * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage. diff --git a/src/storages/inLocalStorage/constants.ts b/src/storages/inLocalStorage/constants.ts new file mode 100644 index 00000000..74624310 --- /dev/null +++ b/src/storages/inLocalStorage/constants.ts @@ -0,0 +1,2 @@ +export const logPrefix = 'storage:localstorage: '; +export const DEFINED = '1'; diff --git a/src/storages/inLocalStorage/index.ts b/src/storages/inLocalStorage/index.ts index 6a4c8624..226d771c 100644 --- a/src/storages/inLocalStorage/index.ts +++ b/src/storages/inLocalStorage/index.ts @@ -10,8 +10,7 @@ import MySegmentsCacheInMemory from '../inMemory/MySegmentsCacheInMemory'; import SplitsCacheInMemory from '../inMemory/SplitsCacheInMemory'; import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser'; import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS'; - -export const logPrefix = 'storage:localstorage: '; +import { logPrefix } from './constants'; export interface InLocalStorageOptions { prefix?: string diff --git a/src/types.ts b/src/types.ts index b60b2bc0..ae2d3fd1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -89,7 +89,7 @@ export interface ISettings { auth: string, streaming: string }, - readonly debug: boolean, + readonly debug: boolean | LogLevel, readonly version: string, features: SplitIO.MockedFeaturesFilePath | SplitIO.MockedFeaturesMap, readonly streamingEnabled: boolean, diff --git a/src/utils/murmur3/murmur3.ts b/src/utils/murmur3/murmur3.ts index 3bdcbc77..434fcbd3 100644 --- a/src/utils/murmur3/murmur3.ts +++ b/src/utils/murmur3/murmur3.ts @@ -1,7 +1,7 @@ /* eslint-disable no-fallthrough */ import { UTF16ToUTF8, x86Fmix, x86Multiply, x86Rotl } from './commons'; -/*! +/* * +----------------------------------------------------------------------------------+ * | murmurHash3.js v3.0.0 (https://github.com/karanlyons/murmurHash3.js) | * | A TypeScript/JavaScript implementation of MurmurHash3's hashing algorithms. | diff --git a/src/utils/murmur3/murmur3_128.ts b/src/utils/murmur3/murmur3_128.ts index 4d5e3cf7..18140e29 100644 --- a/src/utils/murmur3/murmur3_128.ts +++ b/src/utils/murmur3/murmur3_128.ts @@ -6,7 +6,7 @@ const X86 = 'x86'; const X64_ARCHS = ['arm64', 'ppc64', 'x64', 's390x', 'mipsel']; const isX64 = getArchType() === X64; -/*! +/* * +----------------------------------------------------------------------------------+ * | murmurHash3.js v3.0.0 (https://github.com/karanlyons/murmurHash3.js) | * | A TypeScript/JavaScript implementation of MurmurHash3's hashing algorithms. | diff --git a/src/utils/settingsValidation/logger/builtinLogger.ts b/src/utils/settingsValidation/logger/builtinLogger.ts index 9c314a7c..5db9cfb0 100644 --- a/src/utils/settingsValidation/logger/builtinLogger.ts +++ b/src/utils/settingsValidation/logger/builtinLogger.ts @@ -2,17 +2,14 @@ import { isLogLevelString, Logger, LogLevels } from '../../../logger'; import { ILogger } from '../../../logger/types'; import { isLocalStorageAvailable } from '../../env/isLocalStorageAvailable'; import { isNode } from '../../env/isNode'; -import { codesError } from '../../../logger/messages/error'; -import { codesWarn } from '../../../logger/messages/warn'; -import { codesInfo } from '../../../logger/messages/info'; import { codesDebug } from '../../../logger/messages/debug'; import { _Map } from '../../lang/maps'; import { getLogLevel } from './commons'; import { LogLevel } from '../../../types'; -const allCodes = new _Map(codesError.concat(codesWarn, codesInfo, codesDebug)); +const allCodes = new _Map(codesDebug); -// @TODO when integrating with other packages, find the best way to handle initial state per environment +// @TODO set default debug setting instead of initialLogLevel when integrating in JS and Node packages const LS_KEY = 'splitio_debug'; const ENV_VAR_KEY = 'SPLITIO_DEBUG'; From cada7effd0ee637c81dd92d99d25983ef393ffc4 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 25 Mar 2021 14:54:30 -0300 Subject: [PATCH 51/58] nico's feedback --- src/listeners/browser.ts | 6 +++--- src/listeners/node.ts | 13 +++++++------ src/logger/messages/error.ts | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index db4dbd36..a5e14508 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -14,7 +14,7 @@ import { DEBUG_26, DEBUG_27 } from '../logger/constants'; // 'unload' event is used instead of 'beforeunload', since 'unload' is not a cancelable event, so no other listeners can stop the event from occurring. const UNLOAD_DOM_EVENT = 'unload'; -const LOG_EXTRA = 'for unload page event.'; +const EVENT_NAME = 'for unload page event.'; /** * We'll listen for 'unload' event over the window object, since it's the standard way to listen page reload and close. @@ -40,7 +40,7 @@ export default class BrowserSignalListener implements ISignalListener { */ start() { if (typeof window !== 'undefined' && window.addEventListener) { - this.settings.log.debug(DEBUG_26, [LOG_EXTRA]); + this.settings.log.debug(DEBUG_26, [EVENT_NAME]); window.addEventListener(UNLOAD_DOM_EVENT, this.flushData); } } @@ -52,7 +52,7 @@ export default class BrowserSignalListener implements ISignalListener { */ stop() { if (typeof window !== 'undefined' && window.removeEventListener) { - this.settings.log.debug(DEBUG_27, [LOG_EXTRA]); + this.settings.log.debug(DEBUG_27, [EVENT_NAME]); window.removeEventListener(UNLOAD_DOM_EVENT, this.flushData); } } diff --git a/src/listeners/node.ts b/src/listeners/node.ts index 6d97d6c9..3d799c92 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -5,7 +5,8 @@ import { MaybeThenable } from '../dtos/types'; import { ISettings } from '../types'; import { CLEANUP_LB, DEBUG_26, DEBUG_27 } from '../logger/constants'; -const LOG_EXTRA = 'for SIGTERM signal.'; +const SIGTERM = 'SIGTERM'; +const EVENT_NAME = 'for SIGTERM signal.'; /** * We'll listen for SIGTERM since it's the standard signal for server shutdown. @@ -24,15 +25,15 @@ export default class NodeSignalListener implements ISignalListener { } start() { - this.settings.log.debug(DEBUG_26, [LOG_EXTRA]); + this.settings.log.debug(DEBUG_26, [EVENT_NAME]); // eslint-disable-next-line no-undef - process.on('SIGTERM', this._sigtermHandler); + process.on(SIGTERM, this._sigtermHandler); } stop() { - this.settings.log.debug(DEBUG_27, [LOG_EXTRA]); + this.settings.log.debug(DEBUG_27, [EVENT_NAME]); // eslint-disable-next-line no-undef - process.removeListener('SIGTERM', this._sigtermHandler); + process.removeListener(SIGTERM, this._sigtermHandler); } /** @@ -45,7 +46,7 @@ export default class NodeSignalListener implements ISignalListener { // This handler prevented the default behaviour, start again. // eslint-disable-next-line no-undef - process.kill(process.pid, 'SIGTERM'); + process.kill(process.pid, SIGTERM); }; this.settings.log.debug(CLEANUP_LB + 'Split SDK graceful shutdown after SIGTERM.'); diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index b3645e5a..48eaa32b 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -2,7 +2,7 @@ import { ERROR_0, ERROR_2, ERROR_CLIENT_LISTENER, ERROR_4, ERROR_5, ERROR_7, ERR export const codesError: [number, string][] = [ // evaluator - [ERROR_0, ENGINE_COMBINER_LB + 'Invalid Split provided, no valid conditions found'], + [ERROR_0, ENGINE_COMBINER_LB + 'Invalid Split, no valid rules found'], // SDK [ERROR_2, 'logger: Invalid Log Level - No changes to the logs will be applied.'], [ERROR_4, ' Manager instance is not available.'], // @TODO remove if the manager is not pluggable From 2d3de2eae9f8413d673f0053dd99d8ee739f2ff6 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 25 Mar 2021 15:55:40 -0300 Subject: [PATCH 52/58] renamed constants --- src/evaluator/combiners/and.ts | 4 +- src/evaluator/combiners/ifelseif.ts | 8 +- src/evaluator/condition/engineUtils.ts | 4 +- src/evaluator/matchers/all.ts | 4 +- src/evaluator/matchers/between.ts | 4 +- src/evaluator/matchers/boolean.ts | 4 +- src/evaluator/matchers/cont_all.ts | 4 +- src/evaluator/matchers/cont_any.ts | 4 +- src/evaluator/matchers/cont_str.ts | 4 +- src/evaluator/matchers/dependency.ts | 6 +- src/evaluator/matchers/eq.ts | 4 +- src/evaluator/matchers/eq_set.ts | 4 +- src/evaluator/matchers/ew.ts | 4 +- src/evaluator/matchers/gte.ts | 4 +- src/evaluator/matchers/lte.ts | 4 +- src/evaluator/matchers/part_of.ts | 4 +- src/evaluator/matchers/segment.ts | 6 +- src/evaluator/matchers/string.ts | 6 +- src/evaluator/matchers/sw.ts | 4 +- src/evaluator/matchers/whitelist.ts | 4 +- src/evaluator/value/index.ts | 8 +- src/evaluator/value/sanitize.ts | 4 +- src/listeners/browser.ts | 6 +- src/listeners/node.ts | 10 +- src/logger/constants.ts | 236 +++++++++--------- src/logger/messages/debug.ts | 84 +++---- src/logger/messages/error.ts | 24 +- src/logger/messages/info.ts | 46 ++-- src/logger/messages/warn.ts | 38 +-- src/logger/sdkLogger.ts | 4 +- .../__tests__/sdkReadinessManager.spec.ts | 14 +- src/readiness/sdkReadinessManager.ts | 8 +- src/sdkClient/client.ts | 6 +- src/sdkClient/sdkClientMethod.ts | 4 +- src/sdkClient/sdkClientMethodCS.ts | 8 +- src/sdkClient/sdkClientMethodCSWithTT.ts | 8 +- src/sdkFactory/index.ts | 8 +- src/services/splitHttpClient.ts | 6 +- .../offline/syncTasks/fromObjectSyncTask.ts | 6 +- src/sync/polling/pollingManagerCS.ts | 8 +- src/sync/polling/pollingManagerSS.ts | 10 +- .../polling/syncTasks/mySegmentsSyncTask.ts | 4 +- .../polling/syncTasks/segmentsSyncTask.ts | 10 +- src/sync/polling/syncTasks/splitsSyncTask.ts | 14 +- src/sync/streaming/SSEHandler/index.ts | 10 +- src/sync/streaming/pushManager.ts | 16 +- src/sync/streaming/pushManagerCS.ts | 16 +- src/sync/streaming/pushManagerSS.ts | 16 +- src/sync/submitters/eventsSyncTask.ts | 4 +- src/sync/submitters/submitterSyncTask.ts | 10 +- src/sync/syncManagerOnline.ts | 8 +- src/sync/syncTask.ts | 8 +- src/trackers/eventTracker.ts | 6 +- src/trackers/impressionsTracker.ts | 8 +- .../__tests__/isOperational.spec.ts | 4 +- src/utils/inputValidation/apiKey.ts | 8 +- src/utils/inputValidation/isOperational.ts | 4 +- .../__tests__/splitFilters.spec.ts | 8 +- .../logger/pluggableLogger.ts | 2 +- src/utils/settingsValidation/splitFilters.ts | 6 +- 60 files changed, 399 insertions(+), 399 deletions(-) diff --git a/src/evaluator/combiners/and.ts b/src/evaluator/combiners/and.ts index 7f0dbc95..271801dd 100644 --- a/src/evaluator/combiners/and.ts +++ b/src/evaluator/combiners/and.ts @@ -3,7 +3,7 @@ import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { MaybeThenable } from '../../dtos/types'; import { IMatcher } from '../types'; -import { DEBUG_ENGINE_COMBINER_AND } from '../../logger/constants'; +import { ENGINE_COMBINER_AND } from '../../logger/constants'; export default function andCombinerContext(log: ILogger, matchers: IMatcher[]) { @@ -11,7 +11,7 @@ export default function andCombinerContext(log: ILogger, matchers: IMatcher[]) { // Array.prototype.every is supported by target environments const hasMatchedAll = results.every(value => value); - log.debug(DEBUG_ENGINE_COMBINER_AND, [hasMatchedAll]); + log.debug(ENGINE_COMBINER_AND, [hasMatchedAll]); return hasMatchedAll; } diff --git a/src/evaluator/combiners/ifelseif.ts b/src/evaluator/combiners/ifelseif.ts index cf3bf834..9aa162f7 100644 --- a/src/evaluator/combiners/ifelseif.ts +++ b/src/evaluator/combiners/ifelseif.ts @@ -5,12 +5,12 @@ import * as LabelsConstants from '../../utils/labels'; import { CONTROL } from '../../utils/constants'; import { SplitIO } from '../../types'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; -import { DEBUG_1, DEBUG_2, ERROR_0 } from '../../logger/constants'; +import { ENGINE_COMBINER_IFELSEIF, ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, ERROR_ENGINE_COMBINER_IFELSEIF } from '../../logger/constants'; export default function ifElseIfCombinerContext(log: ILogger, predicates: IEvaluator[]): IEvaluator { function unexpectedInputHandler() { - log.error(ERROR_0); + log.error(ERROR_ENGINE_COMBINER_IFELSEIF); return { treatment: CONTROL, @@ -25,13 +25,13 @@ export default function ifElseIfCombinerContext(log: ILogger, predicates: IEvalu const evaluation = predicateResults[i]; if (evaluation !== undefined) { - log.debug(DEBUG_1, [evaluation.treatment]); + log.debug(ENGINE_COMBINER_IFELSEIF, [evaluation.treatment]); return evaluation; } } - log.debug(DEBUG_2); + log.debug(ENGINE_COMBINER_IFELSEIF_NO_TREATMENT); return undefined; } diff --git a/src/evaluator/condition/engineUtils.ts b/src/evaluator/condition/engineUtils.ts index ab4c8fac..bacd3b10 100644 --- a/src/evaluator/condition/engineUtils.ts +++ b/src/evaluator/condition/engineUtils.ts @@ -1,4 +1,4 @@ -import { DEBUG_3 } from '../../logger/constants'; +import { ENGINE_BUCKET } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { bucket } from '../../utils/murmur3/murmur3'; @@ -10,7 +10,7 @@ export function getTreatment(log: ILogger, key: string, seed: number, treatments const treatment = treatments.getTreatmentFor(_bucket); - log.debug(DEBUG_3, [_bucket, key, seed, treatment]); + log.debug(ENGINE_BUCKET, [_bucket, key, seed, treatment]); return treatment; } diff --git a/src/evaluator/matchers/all.ts b/src/evaluator/matchers/all.ts index 5eb43000..8b8c64fb 100644 --- a/src/evaluator/matchers/all.ts +++ b/src/evaluator/matchers/all.ts @@ -1,9 +1,9 @@ -import { DEBUG_4 } from '../../logger/constants'; +import { ENGINE_MATCHER_ALL } from '../../logger/constants'; import { ILogger } from '../../logger/types'; export default function allMatcherContext(log: ILogger) { return function allMatcher(runtimeAttr: string): boolean { - log.debug(DEBUG_4); + log.debug(ENGINE_MATCHER_ALL); return runtimeAttr != null; }; diff --git a/src/evaluator/matchers/between.ts b/src/evaluator/matchers/between.ts index 46c123dd..f56709b3 100644 --- a/src/evaluator/matchers/between.ts +++ b/src/evaluator/matchers/between.ts @@ -1,5 +1,5 @@ import { IBetweenMatcherData } from '../../dtos/types'; -import { DEBUG_5 } from '../../logger/constants'; +import { ENGINE_MATCHER_BETWEEN } from '../../logger/constants'; import { ILogger } from '../../logger/types'; export default function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatcherData) /*: Function */ { @@ -7,7 +7,7 @@ export default function betweenMatcherContext(log: ILogger, ruleVO: IBetweenMatc let isBetween = runtimeAttr >= ruleVO.start && runtimeAttr <= ruleVO.end; - log.debug(DEBUG_5, [runtimeAttr, ruleVO.start, ruleVO.end, isBetween]); + log.debug(ENGINE_MATCHER_BETWEEN, [runtimeAttr, ruleVO.start, ruleVO.end, isBetween]); return isBetween; }; diff --git a/src/evaluator/matchers/boolean.ts b/src/evaluator/matchers/boolean.ts index 87281534..6e64a268 100644 --- a/src/evaluator/matchers/boolean.ts +++ b/src/evaluator/matchers/boolean.ts @@ -1,11 +1,11 @@ -import { DEBUG_6 } from '../../logger/constants'; +import { ENGINE_MATCHER_BOOLEAN } from '../../logger/constants'; import { ILogger } from '../../logger/types'; export default function booleanMatcherContext(log: ILogger, ruleAttr: boolean) /*: Function */ { return function booleanMatcher(runtimeAttr: boolean): boolean { let booleanMatches = ruleAttr === runtimeAttr; - log.debug(DEBUG_6, [ruleAttr, runtimeAttr]); + log.debug(ENGINE_MATCHER_BOOLEAN, [ruleAttr, runtimeAttr]); return booleanMatches; }; diff --git a/src/evaluator/matchers/cont_all.ts b/src/evaluator/matchers/cont_all.ts index 3e7f3d4b..02bc35e1 100644 --- a/src/evaluator/matchers/cont_all.ts +++ b/src/evaluator/matchers/cont_all.ts @@ -1,4 +1,4 @@ -import { DEBUG_7 } from '../../logger/constants'; +import { ENGINE_MATCHER_CONTAINS_ALL } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; @@ -15,7 +15,7 @@ export default function containsAllMatcherContext(log: ILogger, ruleAttr: string } } - log.debug(DEBUG_7, [runtimeAttr, ruleAttr, containsAll]); + log.debug(ENGINE_MATCHER_CONTAINS_ALL, [runtimeAttr, ruleAttr, containsAll]); return containsAll; }; diff --git a/src/evaluator/matchers/cont_any.ts b/src/evaluator/matchers/cont_any.ts index 68565478..69fcdb3e 100644 --- a/src/evaluator/matchers/cont_any.ts +++ b/src/evaluator/matchers/cont_any.ts @@ -1,4 +1,4 @@ -import { DEBUG_8 } from '../../logger/constants'; +import { ENGINE_MATCHER_CONTAINS_ANY } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; @@ -10,7 +10,7 @@ export default function containsAnyMatcherContext(log: ILogger, ruleAttr: string if (findIndex(runtimeAttr, e => e === ruleAttr[i]) >= 0) containsAny = true; } - log.debug(DEBUG_8, [runtimeAttr, ruleAttr, containsAny]); + log.debug(ENGINE_MATCHER_CONTAINS_ANY, [runtimeAttr, ruleAttr, containsAny]); return containsAny; }; diff --git a/src/evaluator/matchers/cont_str.ts b/src/evaluator/matchers/cont_str.ts index 2438d390..0a15d13e 100644 --- a/src/evaluator/matchers/cont_str.ts +++ b/src/evaluator/matchers/cont_str.ts @@ -1,12 +1,12 @@ import { isString } from '../../utils/lang'; import { ILogger } from '../../logger/types'; -import { DEBUG_9 } from '../../logger/constants'; +import { ENGINE_MATCHER_CONTAINS_STRING } from '../../logger/constants'; export default function containsStringMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function containsStringMatcher(runtimeAttr: string): boolean { let contains = ruleAttr.some(e => isString(runtimeAttr) && runtimeAttr.indexOf(e) > -1); - log.debug(DEBUG_9, [runtimeAttr, ruleAttr, contains]); + log.debug(ENGINE_MATCHER_CONTAINS_STRING, [runtimeAttr, ruleAttr, contains]); return contains; }; diff --git a/src/evaluator/matchers/dependency.ts b/src/evaluator/matchers/dependency.ts index f5399024..e3b8723b 100644 --- a/src/evaluator/matchers/dependency.ts +++ b/src/evaluator/matchers/dependency.ts @@ -3,7 +3,7 @@ import { IStorageAsync, IStorageSync } from '../../storages/types'; import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; import { IDependencyMatcherValue, IEvaluation, ISplitEvaluator } from '../types'; -import { DEBUG_10, DEBUG_11 } from '../../logger/constants'; +import { ENGINE_MATCHER_DEPENDENCY, ENGINE_MATCHER_DEPENDENCY_PRE } from '../../logger/constants'; export default function dependencyMatcherContext(log: ILogger, { split, treatments }: IDependencyMatcherData, storage: IStorageSync | IStorageAsync) { @@ -14,13 +14,13 @@ export default function dependencyMatcherContext(log: ILogger, { split, treatmen matches = acceptableTreatments.indexOf(evaluation.treatment as string) !== -1; } - log.debug(DEBUG_10, [parentName, evaluation.treatment, evaluation.label, parentName, acceptableTreatments, matches]); + log.debug(ENGINE_MATCHER_DEPENDENCY, [parentName, evaluation.treatment, evaluation.label, parentName, acceptableTreatments, matches]); return matches; } return function dependencyMatcher({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator): MaybeThenable { - log.debug(DEBUG_11, [split, JSON.stringify(key), attributes ? '\n attributes: ' + JSON.stringify(attributes) : '']); + log.debug(ENGINE_MATCHER_DEPENDENCY_PRE, [split, JSON.stringify(key), attributes ? '\n attributes: ' + JSON.stringify(attributes) : '']); const evaluation = splitEvaluator(log, key, split, attributes, storage); if (thenable(evaluation)) { diff --git a/src/evaluator/matchers/eq.ts b/src/evaluator/matchers/eq.ts index 724b647d..ddccc264 100644 --- a/src/evaluator/matchers/eq.ts +++ b/src/evaluator/matchers/eq.ts @@ -1,11 +1,11 @@ -import { DEBUG_12 } from '../../logger/constants'; +import { ENGINE_MATCHER_EQUAL } from '../../logger/constants'; import { ILogger } from '../../logger/types'; export default function equalToMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ { return function equalToMatcher(runtimeAttr: number): boolean { let isEqual = runtimeAttr === ruleAttr; - log.debug(DEBUG_12, [runtimeAttr, ruleAttr, isEqual]); + log.debug(ENGINE_MATCHER_EQUAL, [runtimeAttr, ruleAttr, isEqual]); return isEqual; }; diff --git a/src/evaluator/matchers/eq_set.ts b/src/evaluator/matchers/eq_set.ts index 9f920e8a..f0fddd27 100644 --- a/src/evaluator/matchers/eq_set.ts +++ b/src/evaluator/matchers/eq_set.ts @@ -1,4 +1,4 @@ -import { DEBUG_13 } from '../../logger/constants'; +import { ENGINE_MATCHER_EQUAL_TO_SET } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { findIndex } from '../../utils/lang'; @@ -12,7 +12,7 @@ export default function equalToSetMatcherContext(log: ILogger, ruleAttr: string[ if (findIndex(ruleAttr, e => e === runtimeAttr[i]) < 0) isEqual = false; } - log.debug(DEBUG_13, [runtimeAttr, ruleAttr, isEqual]); + log.debug(ENGINE_MATCHER_EQUAL_TO_SET, [runtimeAttr, ruleAttr, isEqual]); return isEqual; }; diff --git a/src/evaluator/matchers/ew.ts b/src/evaluator/matchers/ew.ts index a956e133..20d46c63 100644 --- a/src/evaluator/matchers/ew.ts +++ b/src/evaluator/matchers/ew.ts @@ -1,4 +1,4 @@ -import { DEBUG_14 } from '../../logger/constants'; +import { ENGINE_MATCHER_ENDS_WITH } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { endsWith as strEndsWith } from '../../utils/lang'; @@ -6,7 +6,7 @@ export default function endsWithMatcherContext(log: ILogger, ruleAttr: string[]) return function endsWithMatcher(runtimeAttr: string): boolean { let endsWith = ruleAttr.some(e => strEndsWith(runtimeAttr, e)); - log.debug(DEBUG_14, [runtimeAttr, ruleAttr, endsWith]); + log.debug(ENGINE_MATCHER_ENDS_WITH, [runtimeAttr, ruleAttr, endsWith]); return endsWith; }; diff --git a/src/evaluator/matchers/gte.ts b/src/evaluator/matchers/gte.ts index 10e73066..a08f55f5 100644 --- a/src/evaluator/matchers/gte.ts +++ b/src/evaluator/matchers/gte.ts @@ -1,11 +1,11 @@ -import { DEBUG_15 } from '../../logger/constants'; +import { ENGINE_MATCHER_GREATER } from '../../logger/constants'; import { ILogger } from '../../logger/types'; export default function greaterThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: Function */ { return function greaterThanEqualMatcher(runtimeAttr: number): boolean { let isGreaterEqualThan = runtimeAttr >= ruleAttr; - log.debug(DEBUG_15, [runtimeAttr, ruleAttr, isGreaterEqualThan]); + log.debug(ENGINE_MATCHER_GREATER, [runtimeAttr, ruleAttr, isGreaterEqualThan]); return isGreaterEqualThan; }; diff --git a/src/evaluator/matchers/lte.ts b/src/evaluator/matchers/lte.ts index b594b890..06883b94 100644 --- a/src/evaluator/matchers/lte.ts +++ b/src/evaluator/matchers/lte.ts @@ -1,11 +1,11 @@ -import { DEBUG_16 } from '../../logger/constants'; +import { ENGINE_MATCHER_LESS } from '../../logger/constants'; import { ILogger } from '../../logger/types'; export default function lessThanEqualMatcherContext(log: ILogger, ruleAttr: number) /*: function */ { return function lessThanEqualMatcher(runtimeAttr: number): boolean { let isLessEqualThan = runtimeAttr <= ruleAttr; - log.debug(DEBUG_16, [runtimeAttr, ruleAttr, isLessEqualThan]); + log.debug(ENGINE_MATCHER_LESS, [runtimeAttr, ruleAttr, isLessEqualThan]); return isLessEqualThan; }; diff --git a/src/evaluator/matchers/part_of.ts b/src/evaluator/matchers/part_of.ts index 4b410e99..ccabf3e4 100644 --- a/src/evaluator/matchers/part_of.ts +++ b/src/evaluator/matchers/part_of.ts @@ -1,6 +1,6 @@ import { findIndex } from '../../utils/lang'; import { ILogger } from '../../logger/types'; -import { DEBUG_17 } from '../../logger/constants'; +import { ENGINE_MATCHER_PART_OF } from '../../logger/constants'; export default function partOfMatcherContext(log: ILogger, ruleAttr: string[]) /*: Function */ { return function partOfMatcher(runtimeAttr: string[]): boolean { @@ -12,7 +12,7 @@ export default function partOfMatcherContext(log: ILogger, ruleAttr: string[]) / if (findIndex(ruleAttr, e => e === runtimeAttr[i]) < 0) isPartOf = false; } - log.debug(DEBUG_17, [runtimeAttr, ruleAttr, isPartOf]); + log.debug(ENGINE_MATCHER_PART_OF, [runtimeAttr, ruleAttr, isPartOf]); return isPartOf; }; diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index 9f197e0e..7b6f6d4f 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -2,7 +2,7 @@ import { MaybeThenable } from '../../dtos/types'; import { ISegmentsCacheBase } from '../../storages/types'; import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; -import { DEBUG_18, DEBUG_19 } from '../../logger/constants'; +import { ENGINE_MATCHER_SEGMENT_ASYNC, ENGINE_MATCHER_SEGMENT } from '../../logger/constants'; export default function matcherSegmentContext(log: ILogger, segmentName: string, storage: { segments: ISegmentsCacheBase }) { @@ -11,12 +11,12 @@ export default function matcherSegmentContext(log: ILogger, segmentName: string, if (thenable(isInSegment)) { isInSegment.then(result => { - log.debug(DEBUG_18, [segmentName, key, isInSegment]); + log.debug(ENGINE_MATCHER_SEGMENT_ASYNC, [segmentName, key, isInSegment]); return result; }); } else { - log.debug(DEBUG_19, [segmentName, key, isInSegment]); + log.debug(ENGINE_MATCHER_SEGMENT, [segmentName, key, isInSegment]); } return isInSegment; diff --git a/src/evaluator/matchers/string.ts b/src/evaluator/matchers/string.ts index dff34f8d..f0e0512f 100644 --- a/src/evaluator/matchers/string.ts +++ b/src/evaluator/matchers/string.ts @@ -1,4 +1,4 @@ -import { DEBUG_21, DEBUG_20 } from '../../logger/constants'; +import { ENGINE_MATCHER_STRING_INVALID, ENGINE_MATCHER_STRING } from '../../logger/constants'; import { ILogger } from '../../logger/types'; export default function stringMatcherContext(log: ILogger, ruleAttr: string) /*: Function */ { @@ -8,14 +8,14 @@ export default function stringMatcherContext(log: ILogger, ruleAttr: string) /*: try { re = new RegExp(ruleAttr); } catch (e) { - log.debug(DEBUG_21, [ruleAttr]); + log.debug(ENGINE_MATCHER_STRING_INVALID, [ruleAttr]); return false; } let regexMatches = re.test(runtimeAttr); - log.debug(DEBUG_20, [runtimeAttr, ruleAttr, regexMatches ? 'yes' : 'no']); + log.debug(ENGINE_MATCHER_STRING, [runtimeAttr, ruleAttr, regexMatches ? 'yes' : 'no']); return regexMatches; }; diff --git a/src/evaluator/matchers/sw.ts b/src/evaluator/matchers/sw.ts index f2907c4d..e2bfc03e 100644 --- a/src/evaluator/matchers/sw.ts +++ b/src/evaluator/matchers/sw.ts @@ -1,4 +1,4 @@ -import { DEBUG_22 } from '../../logger/constants'; +import { ENGINE_MATCHER_STARTS_WITH } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { startsWith } from '../../utils/lang'; @@ -6,7 +6,7 @@ export default function startsWithMatcherContext(log: ILogger, ruleAttr: string[ return function startsWithMatcher(runtimeAttr: string): boolean { let matches = ruleAttr.some(e => startsWith(runtimeAttr, e)); - log.debug(DEBUG_22, [runtimeAttr, ruleAttr, matches]); + log.debug(ENGINE_MATCHER_STARTS_WITH, [runtimeAttr, ruleAttr, matches]); return matches; }; diff --git a/src/evaluator/matchers/whitelist.ts b/src/evaluator/matchers/whitelist.ts index 142be8ad..b84cb129 100644 --- a/src/evaluator/matchers/whitelist.ts +++ b/src/evaluator/matchers/whitelist.ts @@ -1,12 +1,12 @@ import { setToArray, ISet } from '../../utils/lang/sets'; import { ILogger } from '../../logger/types'; -import { DEBUG_23 } from '../../logger/constants'; +import { ENGINE_MATCHER_WHITELIST } from '../../logger/constants'; export default function whitelistMatcherContext(log: ILogger, ruleAttr: ISet) /*: Function */ { return function whitelistMatcher(runtimeAttr: string): boolean { let isInWhitelist = ruleAttr.has(runtimeAttr); - log.debug(DEBUG_23, [runtimeAttr, setToArray(ruleAttr).join(','), isInWhitelist]); + log.debug(ENGINE_MATCHER_WHITELIST, [runtimeAttr, setToArray(ruleAttr).join(','), isInWhitelist]); return isInWhitelist; }; diff --git a/src/evaluator/value/index.ts b/src/evaluator/value/index.ts index 47a928bc..228d7d0a 100644 --- a/src/evaluator/value/index.ts +++ b/src/evaluator/value/index.ts @@ -2,16 +2,16 @@ import { SplitIO } from '../../types'; import { IMatcherDto } from '../types'; import { ILogger } from '../../logger/types'; import sanitizeValue from './sanitize'; -import { DEBUG_24, WARN_ENGINE_NO_ATTRIBUTES, WARN_ENGINE_INVALID_VALUE } from '../../logger/constants'; +import { ENGINE_VALUE, ENGINE_VALUE_NO_ATTRIBUTES, ENGINE_VALUE_INVALID } from '../../logger/constants'; function parseValue(log: ILogger, key: string, attributeName: string | null, attributes: SplitIO.Attributes) { let value = undefined; if (attributeName) { if (attributes) { value = attributes[attributeName]; - log.debug(DEBUG_24, [attributeName, value]); + log.debug(ENGINE_VALUE, [attributeName, value]); } else { - log.warn(WARN_ENGINE_NO_ATTRIBUTES, [attributeName]); + log.warn(ENGINE_VALUE_NO_ATTRIBUTES, [attributeName]); } } else { value = key; @@ -31,7 +31,7 @@ export default function value(log: ILogger, key: string, matcherDto: IMatcherDto if (sanitizedValue !== undefined) { return sanitizedValue; } else { - log.warn(WARN_ENGINE_INVALID_VALUE, [valueToMatch + (attributeName ? ' for attribute ' + attributeName : '')]); + log.warn(ENGINE_VALUE_INVALID, [valueToMatch + (attributeName ? ' for attribute ' + attributeName : '')]); return; } } diff --git a/src/evaluator/value/sanitize.ts b/src/evaluator/value/sanitize.ts index bbc945f1..46cae859 100644 --- a/src/evaluator/value/sanitize.ts +++ b/src/evaluator/value/sanitize.ts @@ -4,7 +4,7 @@ import { ILogger } from '../../logger/types'; import { isObject, uniq, toString, toNumber } from '../../utils/lang'; import { zeroSinceHH, zeroSinceSS } from '../convertions'; import { matcherTypes, dataTypes } from '../matchers/matcherTypes'; -import { DEBUG_25 } from '../../logger/constants'; +import { ENGINE_SANITIZE } from '../../logger/constants'; function sanitizeNumber(val: any): number | undefined { const num = toNumber(val); @@ -99,7 +99,7 @@ export default function sanitize(log: ILogger, matcherTypeID: number, value: str sanitizedValue = processor(sanitizedValue, attributes); } - log.debug(DEBUG_25, [value, dataType, sanitizedValue instanceof Object ? JSON.stringify(sanitizedValue) : sanitizedValue]); + log.debug(ENGINE_SANITIZE, [value, dataType, sanitizedValue instanceof Object ? JSON.stringify(sanitizedValue) : sanitizedValue]); return sanitizedValue; } diff --git a/src/listeners/browser.ts b/src/listeners/browser.ts index a5e14508..d937448e 100644 --- a/src/listeners/browser.ts +++ b/src/listeners/browser.ts @@ -10,7 +10,7 @@ import { ImpressionsPayload } from '../sync/submitters/types'; import { MaybeThenable } from '../dtos/types'; import { OPTIMIZED, DEBUG } from '../utils/constants'; import objectAssign from 'object-assign'; -import { DEBUG_26, DEBUG_27 } from '../logger/constants'; +import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants'; // 'unload' event is used instead of 'beforeunload', since 'unload' is not a cancelable event, so no other listeners can stop the event from occurring. const UNLOAD_DOM_EVENT = 'unload'; @@ -40,7 +40,7 @@ export default class BrowserSignalListener implements ISignalListener { */ start() { if (typeof window !== 'undefined' && window.addEventListener) { - this.settings.log.debug(DEBUG_26, [EVENT_NAME]); + this.settings.log.debug(CLEANUP_REGISTERING, [EVENT_NAME]); window.addEventListener(UNLOAD_DOM_EVENT, this.flushData); } } @@ -52,7 +52,7 @@ export default class BrowserSignalListener implements ISignalListener { */ stop() { if (typeof window !== 'undefined' && window.removeEventListener) { - this.settings.log.debug(DEBUG_27, [EVENT_NAME]); + this.settings.log.debug(CLEANUP_DEREGISTERING, [EVENT_NAME]); window.removeEventListener(UNLOAD_DOM_EVENT, this.flushData); } } diff --git a/src/listeners/node.ts b/src/listeners/node.ts index 3d799c92..18b01519 100644 --- a/src/listeners/node.ts +++ b/src/listeners/node.ts @@ -3,7 +3,7 @@ import { ISignalListener } from './types'; import thenable from '../utils/promise/thenable'; import { MaybeThenable } from '../dtos/types'; import { ISettings } from '../types'; -import { CLEANUP_LB, DEBUG_26, DEBUG_27 } from '../logger/constants'; +import { logPrefixCleanup, CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants'; const SIGTERM = 'SIGTERM'; const EVENT_NAME = 'for SIGTERM signal.'; @@ -25,13 +25,13 @@ export default class NodeSignalListener implements ISignalListener { } start() { - this.settings.log.debug(DEBUG_26, [EVENT_NAME]); + this.settings.log.debug(CLEANUP_REGISTERING, [EVENT_NAME]); // eslint-disable-next-line no-undef process.on(SIGTERM, this._sigtermHandler); } stop() { - this.settings.log.debug(DEBUG_27, [EVENT_NAME]); + this.settings.log.debug(CLEANUP_DEREGISTERING, [EVENT_NAME]); // eslint-disable-next-line no-undef process.removeListener(SIGTERM, this._sigtermHandler); } @@ -49,14 +49,14 @@ export default class NodeSignalListener implements ISignalListener { process.kill(process.pid, SIGTERM); }; - this.settings.log.debug(CLEANUP_LB + 'Split SDK graceful shutdown after SIGTERM.'); + this.settings.log.debug(logPrefixCleanup + 'Split SDK graceful shutdown after SIGTERM.'); let handlerResult = null; try { handlerResult = this.handler(); } catch (err) { - this.settings.log.error(CLEANUP_LB + `Error with Split SDK graceful shutdown: ${err}`); + this.settings.log.error(logPrefixCleanup + `Error with Split SDK graceful shutdown: ${err}`); } if (thenable(handlerResult)) { diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 775577be..8b0c9397 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -5,109 +5,84 @@ * Modules related to the server-side API (e.g., segmentsSyncTask), platform-specific components (e.g., signal listeners) * and pluggable components (e.g., pluggable integrations & storages) can use the logger with string literals. */ -export const DEBUG_ENGINE_COMBINER_AND = 0; -export const DEBUG_1 = 1; -export const DEBUG_2 = 2; -export const DEBUG_3 = 3; -export const DEBUG_4 = 4; -export const DEBUG_5 = 5; -export const DEBUG_6 = 6; -export const DEBUG_7 = 7; -export const DEBUG_8 = 8; -export const DEBUG_9 = 9; -export const DEBUG_10 = 10; -export const DEBUG_11 = 11; -export const DEBUG_12 = 12; -export const DEBUG_13 = 13; -export const DEBUG_14 = 14; -export const DEBUG_15 = 15; -export const DEBUG_16 = 16; -export const DEBUG_17 = 17; -export const DEBUG_18 = 18; -export const DEBUG_19 = 19; -export const DEBUG_20 = 20; -export const DEBUG_21 = 21; -export const DEBUG_22 = 22; -export const DEBUG_23 = 23; -export const DEBUG_24 = 24; -export const DEBUG_25 = 25; -export const DEBUG_26 = 26; -export const DEBUG_27 = 27; -export const DEBUG_32 = 32; -export const DEBUG_33 = 33; -export const DEBUG_36 = 36; -export const DEBUG_42 = 42; -export const DEBUG_43 = 43; -export const DEBUG_44 = 44; -export const DEBUG_45 = 45; -export const DEBUG_46 = 46; -export const DEBUG_47 = 47; -export const DEBUG_48 = 48; -export const DEBUG_49 = 49; -export const DEBUG_50 = 50; -export const DEBUG_SPLITS_FILTER = 51; +export const ENGINE_COMBINER_AND = 0; +export const ENGINE_COMBINER_IFELSEIF = 1; +export const ENGINE_COMBINER_IFELSEIF_NO_TREATMENT = 2; +export const ENGINE_BUCKET = 3; +export const ENGINE_MATCHER_ALL = 4; +export const ENGINE_MATCHER_BETWEEN = 5; +export const ENGINE_MATCHER_BOOLEAN = 6; +export const ENGINE_MATCHER_CONTAINS_ALL = 7; +export const ENGINE_MATCHER_CONTAINS_ANY = 8; +export const ENGINE_MATCHER_CONTAINS_STRING = 9; +export const ENGINE_MATCHER_DEPENDENCY = 10; +export const ENGINE_MATCHER_DEPENDENCY_PRE = 11; +export const ENGINE_MATCHER_EQUAL = 12; +export const ENGINE_MATCHER_EQUAL_TO_SET = 13; +export const ENGINE_MATCHER_ENDS_WITH = 14; +export const ENGINE_MATCHER_GREATER = 15; +export const ENGINE_MATCHER_LESS = 16; +export const ENGINE_MATCHER_PART_OF = 17; +export const ENGINE_MATCHER_SEGMENT_ASYNC = 18; +export const ENGINE_MATCHER_SEGMENT = 19; +export const ENGINE_MATCHER_STRING = 20; +export const ENGINE_MATCHER_STRING_INVALID = 21; +export const ENGINE_MATCHER_STARTS_WITH = 22; +export const ENGINE_MATCHER_WHITELIST = 23; +export const ENGINE_VALUE = 24; +export const ENGINE_SANITIZE = 25; +export const CLEANUP_REGISTERING = 26; +export const CLEANUP_DEREGISTERING = 27; +export const RETRIEVE_CLIENT_DEFAULT = 32; +export const RETRIEVE_CLIENT_EXISTING = 33; +export const SYNC_OFFLINE_DATA = 36; +export const SYNC_SPLITS_FETCH = 42; +export const SYNC_SPLITS_NEW = 43; +export const SYNC_SPLITS_REMOVED = 44; +export const SYNC_SPLITS_SEGMENTS = 45; +export const STREAMING_NEW_MESSAGE = 46; +export const SYNC_TASK_START = 47; +export const SYNC_TASK_EXECUTE = 48; +export const SYNC_TASK_STOP = 49; +export const IMPRESSIONS_TRACKER_SUCCESS = 50; +export const SETTINGS_SPLITS_FILTER = 51; -export const ERROR_0 = 300; -export const ERROR_2 = 302; -export const ERROR_CLIENT_LISTENER = 303; -export const ERROR_4 = 304; -export const ERROR_5 = 305; -export const ERROR_7 = 307; -export const ERROR_9 = 309; -export const ERROR_10 = 310; -export const ERROR_11 = 311; -export const ERROR_12 = 312; -export const ERROR_EVENT_TYPE_FORMAT = 314; -export const ERROR_NOT_PLAIN_OBJECT = 318; -export const ERROR_SIZE_EXCEEDED = 319; -export const ERROR_NOT_FINITE = 320; -export const ERROR_CLIENT_DESTROYED = 321; -export const ERROR_NULL = 322; -export const ERROR_TOO_LONG = 323; -export const ERROR_INVALID_KEY_OBJECT = 326; -export const ERROR_INVALID = 332; -export const ERROR_EMPTY = 333; -export const ERROR_EMPTY_ARRAY = 334; -export const ERROR_INVALID_IMPRESSIONS_MODE = 338; -export const ERROR_39 = 339; - -export const INFO_CLIENT_READY_FROM_CACHE = 100; -export const INFO_CLIENT_READY = 101; -export const INFO_2 = 102; -export const INFO_3 = 103; -export const INFO_4 = 104; -export const INFO_5 = 105; -export const INFO_6 = 106; -export const INFO_7 = 107; -export const INFO_8 = 108; -export const INFO_9 = 109; -export const INFO_10 = 110; -export const INFO_11 = 111; -export const INFO_12 = 112; -export const INFO_13 = 113; -export const INFO_14 = 114; -export const INFO_15 = 115; -export const INFO_16 = 116; -export const INFO_17 = 117; -export const INFO_18 = 118; -export const INFO_19 = 119; -export const INFO_20 = 120; -export const INFO_21 = 121; +export const CLIENT_READY_FROM_CACHE = 100; +export const CLIENT_READY = 101; +export const IMPRESSION = 102; +export const IMPRESSION_QUEUEING = 103; +export const NEW_SHARED_CLIENT = 104; +export const NEW_FACTORY = 105; +export const RETRIEVE_MANAGER = 106; +export const POLLING_SMART_PAUSING = 107; +export const POLLING_START = 108; +export const POLLING_STOP = 109; +export const SYNC_SPLITS_FETCH_RETRY = 110; +export const STREAMING_REFRESH_TOKEN = 111; +export const STREAMING_RECONNECT = 112; +export const STREAMING_CONNECTING = 113; +export const STREAMING_DISABLED = 114; +export const STREAMING_DISCONNECTING = 115; +export const SUBMITTERS_PUSH_FULL_EVENTS_QUEUE = 116; +export const SUBMITTERS_PUSH = 117; +export const SYNC_START_POLLING = 118; +export const SYNC_CONTINUE_POLLING = 119; +export const SYNC_STOP_POLLING = 120; +export const EVENTS_TRACKER_SUCCESS = 121; -export const WARN_ENGINE_INVALID_VALUE = 200; -export const WARN_ENGINE_NO_ATTRIBUTES = 201; -export const WARN_CLIENT_NO_LISTENER = 202; -export const WARN_4 = 204; -export const WARN_5 = 205; -export const WARN_6 = 206; -export const WARN_7 = 207; -export const WARN_8 = 208; -export const WARN_9 = 209; -export const WARN_10 = 210; -export const WARN_11 = 211; +export const ENGINE_VALUE_INVALID = 200; +export const ENGINE_VALUE_NO_ATTRIBUTES = 201; +export const CLIENT_NO_LISTENER = 202; +export const CLIENT_NOT_READY = 214; +export const SYNC_MYSEGMENTS_FETCH_RETRY = 204; +export const SYNC_SPLITS_FETCH_FAILS = 205; +export const STREAMING_PARSING_ERROR_FAILS = 206; +export const STREAMING_PARSING_MESSAGE_FAILS = 207; +export const STREAMING_FALLBACK = 208; +export const SUBMITTERS_PUSH_FAILS = 209; +export const SUBMITTERS_PUSH_RETRY = 210; export const WARN_SETTING_NULL = 212; export const WARN_TRIMMING_PROPERTIES = 213; -export const WARN_CLIENT_NOT_READY = 214; export const WARN_CONVERTING = 215; export const WARN_TRIMMING = 217; export const WARN_NOT_EXISTENT_SPLIT = 218; @@ -119,23 +94,48 @@ export const WARN_SPLITS_FILTER_INVALID = 223; export const WARN_SPLITS_FILTER_EMPTY = 224; export const WARN_STORAGE_INVALID = 225; export const WARN_API_KEY = 226; +export const ERROR_EVENTS_TRACKER = 211; + +export const ERROR_ENGINE_COMBINER_IFELSEIF = 300; +export const ERROR_LOGLEVEL_INVALID = 302; +export const ERROR_CLIENT_LISTENER = 303; +export const ERROR_MANAGER_NOT_AVAILABLE = 304; +export const ERROR_CLIENT_CANNOT_GET_READY = 305; +export const ERROR_SYNC_OFFLINE_LOADING = 307; +export const ERROR_STREAMING_SSE = 309; +export const ERROR_STREAMING_AUTH = 310; +export const ERROR_IMPRESSIONS_TRACKER = 311; +export const ERROR_IMPRESSIONS_LISTENER = 312; +export const ERROR_EVENT_TYPE_FORMAT = 314; +export const ERROR_NOT_PLAIN_OBJECT = 318; +export const ERROR_SIZE_EXCEEDED = 319; +export const ERROR_NOT_FINITE = 320; +export const ERROR_CLIENT_DESTROYED = 321; +export const ERROR_NULL = 322; +export const ERROR_TOO_LONG = 323; +export const ERROR_INVALID_KEY_OBJECT = 326; +export const ERROR_INVALID = 332; +export const ERROR_EMPTY = 333; +export const ERROR_EMPTY_ARRAY = 334; +export const ERROR_INVALID_IMPRESSIONS_MODE = 338; +export const ERROR_HTTP = 339; -// Log prefixes/tags/categories -export const SETTINGS_LB = 'settings'; -export const INSTANTIATION_LB = 'Factory instantiation'; -export const ENGINE_LB = 'engine'; -export const ENGINE_COMBINER_LB = ENGINE_LB + ':combiner: '; -export const ENGINE_MATCHER_LB = ENGINE_LB + ':matcher: '; -export const ENGINE_VALUE_LB = ENGINE_LB + ':value: '; -export const SYNC_LB = 'sync'; -export const SYNC_MANAGER_LB = SYNC_LB + ':sync-manager: '; -export const SYNC_OFFLINE_LB = SYNC_LB + ':offline: '; -export const SYNC_STREAMING_LB = SYNC_LB + ':streaming: '; -export const SYNC_SPLITS_LB = SYNC_LB + ':split-changes: '; -export const SYNC_SEGMENTS_LB = SYNC_LB + ':segment-changes: '; -export const SYNC_MYSEGMENTS_LB = SYNC_LB + ':my-segments: '; -export const SYNC_POLLING_LB = SYNC_LB + ':polling-manager: '; -export const SYNC_SUBMITTERS_LB = SYNC_LB + ':submitter: '; -export const IMPRESSIONS_TRACKER_LB = 'impressions-tracker: '; -export const EVENTS_TRACKER_LB = 'events-tracker: '; -export const CLEANUP_LB = 'cleanup: '; +// Log prefixes (a.k.a. tags or categories) +export const logPrefixSettings = 'settings'; +export const logPrefixInstantiation = 'Factory instantiation'; +export const logPrefixEngine = 'engine'; +export const logPrefixEngineCombiner = logPrefixEngine + ':combiner: '; +export const logPrefixEngineMatcher = logPrefixEngine + ':matcher: '; +export const logPrefixEngineValue = logPrefixEngine + ':value: '; +export const logPrefixSync = 'sync'; +export const logPrefixSyncManager = logPrefixSync + ':sync-manager: '; +export const logPrefixSyncOffline = logPrefixSync + ':offline: '; +export const logPrefixSyncStreaming = logPrefixSync + ':streaming: '; +export const logPrefixSyncSplits = logPrefixSync + ':split-changes: '; +export const logPrefixSyncSegments = logPrefixSync + ':segment-changes: '; +export const logPrefixSyncMysegments = logPrefixSync + ':my-segments: '; +export const logPrefixSyncPolling = logPrefixSync + ':polling-manager: '; +export const logPrefixSyncSubmitters = logPrefixSync + ':submitter: '; +export const logPrefixImpressionsTracker = 'impressions-tracker: '; +export const logPrefixEventsTracker = 'events-tracker: '; +export const logPrefixCleanup = 'cleanup: '; diff --git a/src/logger/messages/debug.ts b/src/logger/messages/debug.ts index c39fef55..af0098c8 100644 --- a/src/logger/messages/debug.ts +++ b/src/logger/messages/debug.ts @@ -1,50 +1,50 @@ -import { DEBUG_ENGINE_COMBINER_AND, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, DEBUG_7, DEBUG_8, DEBUG_9, DEBUG_10, DEBUG_11, DEBUG_12, DEBUG_13, DEBUG_14, DEBUG_15, DEBUG_16, DEBUG_17, DEBUG_18, DEBUG_19, DEBUG_20, DEBUG_21, DEBUG_22, DEBUG_23, DEBUG_24, DEBUG_25, DEBUG_32, DEBUG_33, DEBUG_36, DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, DEBUG_46, DEBUG_47, DEBUG_48, DEBUG_49, DEBUG_50, DEBUG_SPLITS_FILTER, SETTINGS_LB, ENGINE_LB, ENGINE_COMBINER_LB, ENGINE_MATCHER_LB, ENGINE_VALUE_LB, SYNC_OFFLINE_LB, IMPRESSIONS_TRACKER_LB, SYNC_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, CLEANUP_LB, DEBUG_26, DEBUG_27 } from '../constants'; +import { ENGINE_COMBINER_AND, ENGINE_COMBINER_IFELSEIF, ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, ENGINE_BUCKET, ENGINE_MATCHER_ALL, ENGINE_MATCHER_BETWEEN, ENGINE_MATCHER_BOOLEAN, ENGINE_MATCHER_CONTAINS_ALL, ENGINE_MATCHER_CONTAINS_ANY, ENGINE_MATCHER_CONTAINS_STRING, ENGINE_MATCHER_DEPENDENCY, ENGINE_MATCHER_DEPENDENCY_PRE, ENGINE_MATCHER_EQUAL, ENGINE_MATCHER_EQUAL_TO_SET, ENGINE_MATCHER_ENDS_WITH, ENGINE_MATCHER_GREATER, ENGINE_MATCHER_LESS, ENGINE_MATCHER_PART_OF, ENGINE_MATCHER_SEGMENT_ASYNC, ENGINE_MATCHER_SEGMENT, ENGINE_MATCHER_STRING, ENGINE_MATCHER_STRING_INVALID, ENGINE_MATCHER_STARTS_WITH, ENGINE_MATCHER_WHITELIST, ENGINE_VALUE, ENGINE_SANITIZE, RETRIEVE_CLIENT_DEFAULT, RETRIEVE_CLIENT_EXISTING, SYNC_OFFLINE_DATA, SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, STREAMING_NEW_MESSAGE, SYNC_TASK_START, SYNC_TASK_EXECUTE, SYNC_TASK_STOP, IMPRESSIONS_TRACKER_SUCCESS, SETTINGS_SPLITS_FILTER, logPrefixSettings, logPrefixEngine, logPrefixEngineCombiner, logPrefixEngineMatcher, logPrefixEngineValue, logPrefixSyncOffline, logPrefixImpressionsTracker, logPrefixSync, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixCleanup, CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../constants'; import { codesInfo } from './info'; export const codesDebug: [number, string][] = codesInfo.concat([ // evaluator - [DEBUG_ENGINE_COMBINER_AND, ENGINE_COMBINER_LB + '[andCombiner] evaluates to %s'], - [DEBUG_1, ENGINE_COMBINER_LB + 'Treatment found: %s'], - [DEBUG_2, ENGINE_COMBINER_LB + 'All predicates evaluated, no treatment found.'], - [DEBUG_3, ENGINE_LB + ': using algo "murmur" bucket %s for key %s using seed %s - treatment %s'], - [DEBUG_4, ENGINE_MATCHER_LB + '[allMatcher] is always true'], - [DEBUG_5, ENGINE_MATCHER_LB + '[betweenMatcher] is %s between %s and %s? %s'], - [DEBUG_6, ENGINE_MATCHER_LB + '[booleanMatcher] %s === %s'], - [DEBUG_7, ENGINE_MATCHER_LB + '[containsAllMatcher] %s contains all elements of %s? %s'], - [DEBUG_8, ENGINE_MATCHER_LB + '[containsAnyMatcher] %s contains at least an element of %s? %s'], - [DEBUG_9, ENGINE_MATCHER_LB + '[containsStringMatcher] %s contains %s? %s'], - [DEBUG_10, ENGINE_MATCHER_LB + '[dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], - [DEBUG_11, ENGINE_MATCHER_LB + '[dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], - [DEBUG_12, ENGINE_MATCHER_LB + '[equalToMatcher] is %s equal to %s? %s'], - [DEBUG_13, ENGINE_MATCHER_LB + '[equalToSetMatcher] is %s equal to set %s? %s'], - [DEBUG_14, ENGINE_MATCHER_LB + '[endsWithMatcher] %s ends with %s? %s'], - [DEBUG_15, ENGINE_MATCHER_LB + '[greaterThanEqualMatcher] is %s greater than %s? %s'], - [DEBUG_16, ENGINE_MATCHER_LB + '[lessThanEqualMatcher] is %s less than %s? %s'], - [DEBUG_17, ENGINE_MATCHER_LB + '[partOfMatcher] %s is part of %s? %s'], - [DEBUG_18, ENGINE_MATCHER_LB + '[asyncSegmentMatcher] evaluated %s / %s => %s'], - [DEBUG_19, ENGINE_MATCHER_LB + '[segmentMatcher] evaluated %s / %s => %s'], - [DEBUG_20, ENGINE_MATCHER_LB + '[stringMatcher] does %s matches with %s? %s'], - [DEBUG_21, ENGINE_MATCHER_LB + '[stringMatcher] %s is an invalid regex'], - [DEBUG_22, ENGINE_MATCHER_LB + '[startsWithMatcher] %s starts with %s? %s'], - [DEBUG_23, ENGINE_MATCHER_LB + '[whitelistMatcher] evaluated %s in [%s] => %s'], - [DEBUG_24, ENGINE_VALUE_LB + 'Extracted attribute [%s], [%s] will be used for matching.'], - [DEBUG_25, ENGINE_LB + ':sanitize: Attempted to sanitize [%s] which should be of type [%s]. Sanitized and processed value => [%s]'], + [ENGINE_COMBINER_AND, logPrefixEngineCombiner + '[andCombiner] evaluates to %s'], + [ENGINE_COMBINER_IFELSEIF, logPrefixEngineCombiner + 'Treatment found: %s'], + [ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, logPrefixEngineCombiner + 'All predicates evaluated, no treatment found.'], + [ENGINE_BUCKET, logPrefixEngine + ': using algo "murmur" bucket %s for key %s using seed %s - treatment %s'], + [ENGINE_MATCHER_ALL, logPrefixEngineMatcher + '[allMatcher] is always true'], + [ENGINE_MATCHER_BETWEEN, logPrefixEngineMatcher + '[betweenMatcher] is %s between %s and %s? %s'], + [ENGINE_MATCHER_BOOLEAN, logPrefixEngineMatcher + '[booleanMatcher] %s === %s'], + [ENGINE_MATCHER_CONTAINS_ALL, logPrefixEngineMatcher + '[containsAllMatcher] %s contains all elements of %s? %s'], + [ENGINE_MATCHER_CONTAINS_ANY, logPrefixEngineMatcher + '[containsAnyMatcher] %s contains at least an element of %s? %s'], + [ENGINE_MATCHER_CONTAINS_STRING, logPrefixEngineMatcher + '[containsStringMatcher] %s contains %s? %s'], + [ENGINE_MATCHER_DEPENDENCY, logPrefixEngineMatcher + '[dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], + [ENGINE_MATCHER_DEPENDENCY_PRE, logPrefixEngineMatcher + '[dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], + [ENGINE_MATCHER_EQUAL, logPrefixEngineMatcher + '[equalToMatcher] is %s equal to %s? %s'], + [ENGINE_MATCHER_EQUAL_TO_SET, logPrefixEngineMatcher + '[equalToSetMatcher] is %s equal to set %s? %s'], + [ENGINE_MATCHER_ENDS_WITH, logPrefixEngineMatcher + '[endsWithMatcher] %s ends with %s? %s'], + [ENGINE_MATCHER_GREATER, logPrefixEngineMatcher + '[greaterThanEqualMatcher] is %s greater than %s? %s'], + [ENGINE_MATCHER_LESS, logPrefixEngineMatcher + '[lessThanEqualMatcher] is %s less than %s? %s'], + [ENGINE_MATCHER_PART_OF, logPrefixEngineMatcher + '[partOfMatcher] %s is part of %s? %s'], + [ENGINE_MATCHER_SEGMENT_ASYNC, logPrefixEngineMatcher + '[asyncSegmentMatcher] evaluated %s / %s => %s'], + [ENGINE_MATCHER_SEGMENT, logPrefixEngineMatcher + '[segmentMatcher] evaluated %s / %s => %s'], + [ENGINE_MATCHER_STRING, logPrefixEngineMatcher + '[stringMatcher] does %s matches with %s? %s'], + [ENGINE_MATCHER_STRING_INVALID, logPrefixEngineMatcher + '[stringMatcher] %s is an invalid regex'], + [ENGINE_MATCHER_STARTS_WITH, logPrefixEngineMatcher + '[startsWithMatcher] %s starts with %s? %s'], + [ENGINE_MATCHER_WHITELIST, logPrefixEngineMatcher + '[whitelistMatcher] evaluated %s in [%s] => %s'], + [ENGINE_VALUE, logPrefixEngineValue + 'Extracted attribute [%s], [%s] will be used for matching.'], + [ENGINE_SANITIZE, logPrefixEngine + ':sanitize: Attempted to sanitize [%s] which should be of type [%s]. Sanitized and processed value => [%s]'], // SDK - [DEBUG_26, CLEANUP_LB + 'Registering cleanup handler %s'], - [DEBUG_27, CLEANUP_LB + 'Deregistering cleanup handler %s'], - [DEBUG_32, ' Retrieving default SDK client.'], - [DEBUG_33, ' Retrieving existing SDK client.'], + [CLEANUP_REGISTERING, logPrefixCleanup + 'Registering cleanup handler %s'], + [CLEANUP_DEREGISTERING, logPrefixCleanup + 'Deregistering cleanup handler %s'], + [RETRIEVE_CLIENT_DEFAULT, ' Retrieving default SDK client.'], + [RETRIEVE_CLIENT_EXISTING, ' Retrieving existing SDK client.'], // synchronizer - [DEBUG_36, SYNC_OFFLINE_LB + 'Splits data: \n%s'], - [DEBUG_42, SYNC_SPLITS_LB + 'Spin up split update using since = %s'], - [DEBUG_43, SYNC_SPLITS_LB + 'New splits %s'], - [DEBUG_44, SYNC_SPLITS_LB + 'Removed splits %s'], - [DEBUG_45, SYNC_SPLITS_LB + 'Segment names collected %s'], - [DEBUG_46, SYNC_STREAMING_LB + 'New SSE message received, with data: %s.'], - [DEBUG_47, SYNC_LB + ': Starting %s. Running each %s millis'], - [DEBUG_48, SYNC_LB + ': Running %s'], - [DEBUG_49, SYNC_LB + ': Stopping %s'], - [DEBUG_50, IMPRESSIONS_TRACKER_LB + 'Successfully stored %s impression%s.'], + [SYNC_OFFLINE_DATA, logPrefixSyncOffline + 'Splits data: \n%s'], + [SYNC_SPLITS_FETCH, logPrefixSyncSplits + 'Spin up split update using since = %s'], + [SYNC_SPLITS_NEW, logPrefixSyncSplits + 'New splits %s'], + [SYNC_SPLITS_REMOVED, logPrefixSyncSplits + 'Removed splits %s'], + [SYNC_SPLITS_SEGMENTS, logPrefixSyncSplits + 'Segment names collected %s'], + [STREAMING_NEW_MESSAGE, logPrefixSyncStreaming + 'New SSE message received, with data: %s.'], + [SYNC_TASK_START, logPrefixSync + ': Starting %s. Running each %s millis'], + [SYNC_TASK_EXECUTE, logPrefixSync + ': Running %s'], + [SYNC_TASK_STOP, logPrefixSync + ': Stopping %s'], + [IMPRESSIONS_TRACKER_SUCCESS, logPrefixImpressionsTracker + 'Successfully stored %s impression%s.'], // initialization / settings validation - [DEBUG_SPLITS_FILTER, SETTINGS_LB + ': splits filtering criteria is "%s".'] + [SETTINGS_SPLITS_FILTER, logPrefixSettings + ': splits filtering criteria is "%s".'] ]); diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index 48eaa32b..54e0c188 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -1,19 +1,19 @@ -import { ERROR_0, ERROR_2, ERROR_CLIENT_LISTENER, ERROR_4, ERROR_5, ERROR_7, ERROR_9, ERROR_10, ERROR_11, ERROR_12, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_CLIENT_DESTROYED, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_IMPRESSIONS_MODE, ERROR_39, SETTINGS_LB, ENGINE_COMBINER_LB, SYNC_OFFLINE_LB, SYNC_STREAMING_LB, IMPRESSIONS_TRACKER_LB } from '../constants'; +import { ERROR_ENGINE_COMBINER_IFELSEIF, ERROR_LOGLEVEL_INVALID, ERROR_CLIENT_LISTENER, ERROR_MANAGER_NOT_AVAILABLE, ERROR_CLIENT_CANNOT_GET_READY, ERROR_SYNC_OFFLINE_LOADING, ERROR_STREAMING_SSE, ERROR_STREAMING_AUTH, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_CLIENT_DESTROYED, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_IMPRESSIONS_MODE, ERROR_HTTP, logPrefixSettings, logPrefixEngineCombiner, logPrefixSyncOffline, logPrefixSyncStreaming, logPrefixImpressionsTracker } from '../constants'; export const codesError: [number, string][] = [ // evaluator - [ERROR_0, ENGINE_COMBINER_LB + 'Invalid Split, no valid rules found'], + [ERROR_ENGINE_COMBINER_IFELSEIF, logPrefixEngineCombiner + 'Invalid Split, no valid rules found'], // SDK - [ERROR_2, 'logger: Invalid Log Level - No changes to the logs will be applied.'], - [ERROR_4, ' Manager instance is not available.'], // @TODO remove if the manager is not pluggable - [ERROR_5, ' The SDK will not get ready. Reason: %s'], + [ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'], + [ERROR_MANAGER_NOT_AVAILABLE, ' Manager instance is not available.'], // @TODO remove if the manager is not pluggable + [ERROR_CLIENT_CANNOT_GET_READY, ' The SDK will not get ready. Reason: %s'], // synchronizer - [ERROR_7, SYNC_OFFLINE_LB + 'There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], - [ERROR_9, SYNC_STREAMING_LB + 'Fail to connect to streaming, with error message: %s'], - [ERROR_10, SYNC_STREAMING_LB + 'Failed to authenticate for streaming. Error: "%s".'], - [ERROR_11, IMPRESSIONS_TRACKER_LB + 'Could not store impressions bulk with %s impression%s. Error: %s'], - [ERROR_12, IMPRESSIONS_TRACKER_LB + 'Impression listener logImpression method threw: %s.'], - [ERROR_39, ' Response status is not OK. Status: %s. URL: %s. Message: %s'], + [ERROR_SYNC_OFFLINE_LOADING, logPrefixSyncOffline + 'There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], + [ERROR_STREAMING_SSE, logPrefixSyncStreaming + 'Fail to connect to streaming, with error message: %s'], + [ERROR_STREAMING_AUTH, logPrefixSyncStreaming + 'Failed to authenticate for streaming. Error: "%s".'], + [ERROR_IMPRESSIONS_TRACKER, logPrefixImpressionsTracker + 'Could not store impressions bulk with %s impression%s. Error: %s'], + [ERROR_IMPRESSIONS_LISTENER, logPrefixImpressionsTracker + 'Impression listener logImpression method threw: %s.'], + [ERROR_HTTP, ' Response status is not OK. Status: %s. URL: %s. Message: %s'], // client status [ERROR_CLIENT_LISTENER, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], [ERROR_CLIENT_DESTROYED, '%s: Client has already been destroyed - no calls possible.'], @@ -29,5 +29,5 @@ export const codesError: [number, string][] = [ [ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'], [ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'], // initialization / settings validation - [ERROR_INVALID_IMPRESSIONS_MODE, SETTINGS_LB + ': you passed an invalid "impressionsMode". It should be one of the following values: %s. Defaulting to "%s" mode.'], + [ERROR_INVALID_IMPRESSIONS_MODE, logPrefixSettings + ': you passed an invalid "impressionsMode". It should be one of the following values: %s. Defaulting to "%s" mode.'], ]; diff --git a/src/logger/messages/info.ts b/src/logger/messages/info.ts index 16f542c6..9a9c237e 100644 --- a/src/logger/messages/info.ts +++ b/src/logger/messages/info.ts @@ -1,32 +1,32 @@ -import { INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, INFO_2, INFO_3, INFO_4, INFO_5, INFO_6, INFO_7, INFO_8, INFO_9, INFO_10, INFO_11, INFO_12, INFO_13, INFO_14, INFO_15, INFO_16, INFO_17, INFO_18, INFO_19, INFO_20, INFO_21, EVENTS_TRACKER_LB, SYNC_MANAGER_LB, SYNC_POLLING_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, SYNC_SUBMITTERS_LB, IMPRESSIONS_TRACKER_LB } from '../constants'; +import { CLIENT_READY_FROM_CACHE, CLIENT_READY, IMPRESSION, IMPRESSION_QUEUEING, NEW_SHARED_CLIENT, NEW_FACTORY, RETRIEVE_MANAGER, POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP, SYNC_SPLITS_FETCH_RETRY, STREAMING_REFRESH_TOKEN, STREAMING_RECONNECT, STREAMING_CONNECTING, STREAMING_DISABLED, STREAMING_DISCONNECTING, SUBMITTERS_PUSH_FULL_EVENTS_QUEUE, SUBMITTERS_PUSH, SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING, EVENTS_TRACKER_SUCCESS, logPrefixEventsTracker, logPrefixSyncManager, logPrefixSyncPolling, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixSyncSubmitters, logPrefixImpressionsTracker } from '../constants'; import { codesWarn } from './warn'; const READY_MSG = 'Split SDK is ready'; export const codesInfo: [number, string][] = codesWarn.concat([ // client status - [INFO_CLIENT_READY_FROM_CACHE, READY_MSG + ' from cache'], - [INFO_CLIENT_READY, READY_MSG], + [CLIENT_READY_FROM_CACHE, READY_MSG + ' from cache'], + [CLIENT_READY, READY_MSG], // SDK - [INFO_2, IMPRESSIONS_TRACKER_LB +'Split: %s. Key: %s. Evaluation: %s. Label: %s'], - [INFO_3, IMPRESSIONS_TRACKER_LB +'Queueing corresponding impression.'], - [INFO_4, ' New shared client instance created.'], - [INFO_5, ' New Split SDK instance created.'], - [INFO_6, ' Manager instance retrieved.'], - [INFO_21, EVENTS_TRACKER_LB + 'Successfully qeued %s'], + [IMPRESSION, logPrefixImpressionsTracker +'Split: %s. Key: %s. Evaluation: %s. Label: %s'], + [IMPRESSION_QUEUEING, logPrefixImpressionsTracker +'Queueing corresponding impression.'], + [NEW_SHARED_CLIENT, ' New shared client instance created.'], + [NEW_FACTORY, ' New Split SDK instance created.'], + [RETRIEVE_MANAGER, ' Manager instance retrieved.'], + [EVENTS_TRACKER_SUCCESS, logPrefixEventsTracker + 'Successfully qeued %s'], // synchronizer - [INFO_7, SYNC_POLLING_LB + 'Turning segments data polling %s.'], - [INFO_8, SYNC_POLLING_LB + 'Starting polling'], - [INFO_9, SYNC_POLLING_LB + 'Stopping polling'], - [INFO_10, SYNC_SPLITS_LB + 'Retrying download of splits #%s. Reason: %s'], - [INFO_16, SYNC_SUBMITTERS_LB + 'Flushing full events queue and reseting timer.'], - [INFO_17, SYNC_SUBMITTERS_LB + 'Pushing %s %s.'], - [INFO_11, SYNC_STREAMING_LB + 'Refreshing streaming token in %s seconds.'], - [INFO_12, SYNC_STREAMING_LB + 'Attempting to reconnect in %s seconds.'], - [INFO_13, SYNC_STREAMING_LB + 'Connecting to streaming.'], - [INFO_14, SYNC_STREAMING_LB + 'Streaming is disabled for given Api key. Switching to polling mode.'], - [INFO_15, SYNC_STREAMING_LB + 'Disconnecting from streaming.'], - [INFO_18, SYNC_MANAGER_LB + 'Streaming not available. Starting polling.'], - [INFO_19, SYNC_MANAGER_LB + 'Streaming couldn\'t connect. Continue polling.'], - [INFO_20, SYNC_MANAGER_LB + 'Streaming (re)connected. Syncing and stopping polling.'], + [POLLING_SMART_PAUSING, logPrefixSyncPolling + 'Turning segments data polling %s.'], + [POLLING_START, logPrefixSyncPolling + 'Starting polling'], + [POLLING_STOP, logPrefixSyncPolling + 'Stopping polling'], + [SYNC_SPLITS_FETCH_RETRY, logPrefixSyncSplits + 'Retrying download of splits #%s. Reason: %s'], + [SUBMITTERS_PUSH_FULL_EVENTS_QUEUE, logPrefixSyncSubmitters + 'Flushing full events queue and reseting timer.'], + [SUBMITTERS_PUSH, logPrefixSyncSubmitters + 'Pushing %s %s.'], + [STREAMING_REFRESH_TOKEN, logPrefixSyncStreaming + 'Refreshing streaming token in %s seconds.'], + [STREAMING_RECONNECT, logPrefixSyncStreaming + 'Attempting to reconnect in %s seconds.'], + [STREAMING_CONNECTING, logPrefixSyncStreaming + 'Connecting to streaming.'], + [STREAMING_DISABLED, logPrefixSyncStreaming + 'Streaming is disabled for given Api key. Switching to polling mode.'], + [STREAMING_DISCONNECTING, logPrefixSyncStreaming + 'Disconnecting from streaming.'], + [SYNC_START_POLLING, logPrefixSyncManager + 'Streaming not available. Starting polling.'], + [SYNC_CONTINUE_POLLING, logPrefixSyncManager + 'Streaming couldn\'t connect. Continue polling.'], + [SYNC_STOP_POLLING, logPrefixSyncManager + 'Streaming (re)connected. Syncing and stopping polling.'], ]); diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index c3338be4..96d36127 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -1,23 +1,23 @@ -import { WARN_ENGINE_INVALID_VALUE, WARN_ENGINE_NO_ATTRIBUTES, WARN_CLIENT_NO_LISTENER, WARN_4, WARN_5, WARN_6, WARN_7, WARN_8, WARN_9, WARN_10, WARN_11, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, WARN_CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, SETTINGS_LB, ENGINE_VALUE_LB, EVENTS_TRACKER_LB, SYNC_MYSEGMENTS_LB, SYNC_SPLITS_LB, SYNC_STREAMING_LB, SYNC_SUBMITTERS_LB } from '../constants'; +import { ENGINE_VALUE_INVALID, ENGINE_VALUE_NO_ATTRIBUTES, CLIENT_NO_LISTENER, SYNC_MYSEGMENTS_FETCH_RETRY, SYNC_SPLITS_FETCH_FAILS, STREAMING_PARSING_ERROR_FAILS, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_FALLBACK, SUBMITTERS_PUSH_FAILS, SUBMITTERS_PUSH_RETRY, ERROR_EVENTS_TRACKER, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, logPrefixSettings, logPrefixEngineValue, logPrefixEventsTracker, logPrefixSyncMysegments, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixSyncSubmitters } from '../constants'; import { codesError } from './error'; export const codesWarn: [number, string][] = codesError.concat([ // evaluator - [WARN_ENGINE_INVALID_VALUE, ENGINE_VALUE_LB + 'Value %s doesn\'t match with expected type.'], - [WARN_ENGINE_NO_ATTRIBUTES, ENGINE_VALUE_LB + 'Defined attribute [%s], no attributes received.'], + [ENGINE_VALUE_INVALID, logPrefixEngineValue + 'Value %s doesn\'t match with expected type.'], + [ENGINE_VALUE_NO_ATTRIBUTES, logPrefixEngineValue + 'Defined attribute [%s], no attributes received.'], // synchronizer - [WARN_4, SYNC_MYSEGMENTS_LB + 'Retrying download of segments #%s. Reason: %s'], - [WARN_5, SYNC_SPLITS_LB + 'Error while doing fetch of Splits. %s'], - [WARN_6, SYNC_STREAMING_LB + 'Error parsing SSE error notification: %s'], - [WARN_7, SYNC_STREAMING_LB + 'Error parsing new SSE message notification: %s'], - [WARN_8, SYNC_STREAMING_LB + 'Falling back to polling mode. Reason: %s'], - [WARN_9, SYNC_SUBMITTERS_LB + 'Droping %s %s after retry. Reason: %s.'], - [WARN_10, SYNC_SUBMITTERS_LB + 'Failed to push %s %s, keeping data to retry on next iteration. Reason: %s.'], + [SYNC_MYSEGMENTS_FETCH_RETRY, logPrefixSyncMysegments + 'Retrying download of segments #%s. Reason: %s'], + [SYNC_SPLITS_FETCH_FAILS, logPrefixSyncSplits + 'Error while doing fetch of Splits. %s'], + [STREAMING_PARSING_ERROR_FAILS, logPrefixSyncStreaming + 'Error parsing SSE error notification: %s'], + [STREAMING_PARSING_MESSAGE_FAILS, logPrefixSyncStreaming + 'Error parsing new SSE message notification: %s'], + [STREAMING_FALLBACK, logPrefixSyncStreaming + 'Falling back to polling mode. Reason: %s'], + [SUBMITTERS_PUSH_FAILS, logPrefixSyncSubmitters + 'Droping %s %s after retry. Reason: %s.'], + [SUBMITTERS_PUSH_RETRY, logPrefixSyncSubmitters + 'Failed to push %s %s, keeping data to retry on next iteration. Reason: %s.'], // SDK - [WARN_11, EVENTS_TRACKER_LB + 'Failed to queue %s'], + [ERROR_EVENTS_TRACKER, logPrefixEventsTracker + 'Failed to queue %s'], // client status - [WARN_CLIENT_NOT_READY, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], - [WARN_CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], + [CLIENT_NOT_READY, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], + [CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], // input validation [WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'], [WARN_TRIMMING_PROPERTIES, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], @@ -27,10 +27,10 @@ export const codesWarn: [number, string][] = codesError.concat([ [WARN_LOWERCASE_TRAFFIC_TYPE, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], [WARN_NOT_EXISTENT_TT, '%s: traffic type "%s" does not have any corresponding split in this environment, make sure you\'re tracking your events to a valid traffic type defined in the web console.'], // initialization / settings validation - [WARN_INTEGRATION_INVALID, SETTINGS_LB+': %s integration %s at settings %s invalid. %s'], - [WARN_SPLITS_FILTER_IGNORED, SETTINGS_LB+': split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'], - [WARN_SPLITS_FILTER_INVALID, SETTINGS_LB+': split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'], - [WARN_SPLITS_FILTER_EMPTY, SETTINGS_LB+': splitFilters configuration must be a non-empty array of filter objects.'], - [WARN_STORAGE_INVALID, SETTINGS_LB+': The provided storage is invalid. Fallbacking into default MEMORY storage'], - [WARN_API_KEY, SETTINGS_LB+': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'] + [WARN_INTEGRATION_INVALID, logPrefixSettings+': %s integration %s at settings %s invalid. %s'], + [WARN_SPLITS_FILTER_IGNORED, logPrefixSettings+': split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'], + [WARN_SPLITS_FILTER_INVALID, logPrefixSettings+': split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'], + [WARN_SPLITS_FILTER_EMPTY, logPrefixSettings+': splitFilters configuration must be a non-empty array of filter objects.'], + [WARN_STORAGE_INVALID, logPrefixSettings+': The provided storage is invalid. Fallbacking into default MEMORY storage'], + [WARN_API_KEY, logPrefixSettings+': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'] ]); diff --git a/src/logger/sdkLogger.ts b/src/logger/sdkLogger.ts index 32840ea5..41c3635a 100644 --- a/src/logger/sdkLogger.ts +++ b/src/logger/sdkLogger.ts @@ -1,7 +1,7 @@ import { LogLevels, isLogLevelString } from './index'; import { ILoggerAPI } from '../types'; import { ILogger } from './types'; -import { ERROR_2 } from './constants'; +import { ERROR_LOGLEVEL_INVALID } from './constants'; /** * The public Logger utility API exposed via SplitFactory, used to update the log level. @@ -14,7 +14,7 @@ export function createLoggerAPI(log: ILogger): ILoggerAPI { if (isLogLevelString(logLevel)) { log.setLogLevel(logLevel); } else { - log.error(ERROR_2); + log.error(ERROR_LOGLEVEL_INVALID); } } diff --git a/src/readiness/__tests__/sdkReadinessManager.spec.ts b/src/readiness/__tests__/sdkReadinessManager.spec.ts index cde58e8f..ca032224 100644 --- a/src/readiness/__tests__/sdkReadinessManager.spec.ts +++ b/src/readiness/__tests__/sdkReadinessManager.spec.ts @@ -4,7 +4,7 @@ import { IEventEmitter } from '../../types'; import { SDK_READY, SDK_READY_FROM_CACHE, SDK_READY_TIMED_OUT, SDK_UPDATE } from '../constants'; import sdkReadinessManagerFactory from '../sdkReadinessManager'; import { IReadinessManager } from '../types'; -import { ERROR_CLIENT_LISTENER, INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, WARN_CLIENT_NO_LISTENER } from '../../logger/constants'; +import { ERROR_CLIENT_LISTENER, CLIENT_READY_FROM_CACHE, CLIENT_READY, CLIENT_NO_LISTENER } from '../../logger/constants'; const EventEmitterMock = jest.fn(() => ({ on: jest.fn(), @@ -82,7 +82,7 @@ describe('SDK Readiness Manager - Event emitter', () => { const readyFromCacheEventCB = gateMock.once.mock.calls[2][1]; readyFromCacheEventCB(); expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY_FROM_CACHE event fires, we get a info message. - expect(loggerMock.info).toBeCalledWith(INFO_CLIENT_READY_FROM_CACHE); // Telling us the SDK is ready to be used with data from cache. + expect(loggerMock.info).toBeCalledWith(CLIENT_READY_FROM_CACHE); // Telling us the SDK is ready to be used with data from cache. }); test('The event callbacks should work as expected - SDK_READY emits with no callbacks', () => { @@ -94,10 +94,10 @@ describe('SDK Readiness Manager - Event emitter', () => { emitReadyEvent(sdkReadinessManager.readinessManager); expect(loggerMock.warn.mock.calls.length).toBe(1); // If the SDK_READY event fires and we have no callbacks for it (neither event nor ready promise) we get a warning. - expect(loggerMock.warn).toBeCalledWith(WARN_CLIENT_NO_LISTENER); // Telling us there were no listeners and evaluations before this point may have been incorrect. + expect(loggerMock.warn).toBeCalledWith(CLIENT_NO_LISTENER); // Telling us there were no listeners and evaluations before this point may have been incorrect. expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY event fires, we get a info message. - expect(loggerMock.info).toBeCalledWith(INFO_CLIENT_READY); // Telling us the SDK is ready. + expect(loggerMock.info).toBeCalledWith(CLIENT_READY); // Telling us the SDK is ready. // Now it's marked as ready. addListenerCB('this event we do not care'); @@ -126,7 +126,7 @@ describe('SDK Readiness Manager - Event emitter', () => { expect(loggerMock.error.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY event fires, we get a info message. - expect(loggerMock.info).toBeCalledWith(INFO_CLIENT_READY); // Telling us the SDK is ready. + expect(loggerMock.info).toBeCalledWith(CLIENT_READY); // Telling us the SDK is ready. }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { @@ -146,7 +146,7 @@ describe('SDK Readiness Manager - Event emitter', () => { removeListenerCB(SDK_READY); emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn).toBeCalledWith(WARN_CLIENT_NO_LISTENER); // We get the warning. + expect(loggerMock.warn).toBeCalledWith(CLIENT_NO_LISTENER); // We get the warning. }); test('The event callbacks should work as expected - If we end up removing the listeners for SDK_READY, it behaves as if it had none', () => { @@ -272,7 +272,7 @@ describe('SDK Readiness Manager - Ready promise', () => { const readyEventCB = sdkReadinessManager.readinessManager.gate.once.mock.calls[0][1]; readyEventCB(); - expect(loggerMock.warn).toBeCalledWith(WARN_CLIENT_NO_LISTENER); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise. + expect(loggerMock.warn).toBeCalledWith(CLIENT_NO_LISTENER); // We would get the warning if the SDK get\'s ready before attaching any callbacks to ready promise. loggerMock.warn.mockClear(); readyPromise.then(() => { diff --git a/src/readiness/sdkReadinessManager.ts b/src/readiness/sdkReadinessManager.ts index f1ada0fa..07f8f284 100644 --- a/src/readiness/sdkReadinessManager.ts +++ b/src/readiness/sdkReadinessManager.ts @@ -5,7 +5,7 @@ import { ISdkReadinessManager } from './types'; import { IEventEmitter } from '../types'; import { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from './constants'; import { ILogger } from '../logger/types'; -import { ERROR_CLIENT_LISTENER, INFO_CLIENT_READY_FROM_CACHE, INFO_CLIENT_READY, WARN_CLIENT_NO_LISTENER } from '../logger/constants'; +import { ERROR_CLIENT_LISTENER, CLIENT_READY_FROM_CACHE, CLIENT_READY, CLIENT_NO_LISTENER } from '../logger/constants'; const NEW_LISTENER_EVENT = 'newListener'; const REMOVE_LISTENER_EVENT = 'removeListener'; @@ -46,7 +46,7 @@ export default function sdkReadinessManagerFactory( const readyPromise = generateReadyPromise(); readinessManager.gate.once(SDK_READY_FROM_CACHE, () => { - log.info(INFO_CLIENT_READY_FROM_CACHE); + log.info(CLIENT_READY_FROM_CACHE); }); // default onRejected handler, that just logs the error, if ready promise doesn't have one. @@ -57,9 +57,9 @@ export default function sdkReadinessManagerFactory( function generateReadyPromise() { const promise = promiseWrapper(new Promise((resolve, reject) => { readinessManager.gate.once(SDK_READY, () => { - log.info(INFO_CLIENT_READY); + log.info(CLIENT_READY); - if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn(WARN_CLIENT_NO_LISTENER); + if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled()) log.warn(CLIENT_NO_LISTENER); resolve(); }); readinessManager.gate.once(SDK_READY_TIMED_OUT, reject); diff --git a/src/sdkClient/client.ts b/src/sdkClient/client.ts index 0dfd6dd9..e9f178d8 100644 --- a/src/sdkClient/client.ts +++ b/src/sdkClient/client.ts @@ -8,7 +8,7 @@ import { CONTROL } from '../utils/constants'; import { IClientFactoryParams } from './types'; import { IEvaluationResult } from '../evaluator/types'; import { SplitIO, ImpressionDTO } from '../types'; -import { INFO_2, INFO_3 } from '../logger/constants'; +import { IMPRESSION, IMPRESSION_QUEUEING } from '../logger/constants'; /** @@ -75,10 +75,10 @@ export default function clientFactory(params: IClientFactoryParams): SplitIO.ICl } const { treatment, label, changeNumber, config = null } = evaluation; - log.info(INFO_2, [splitName, matchingKey, treatment, label]); + log.info(IMPRESSION, [splitName, matchingKey, treatment, label]); if (validateSplitExistance(log, readinessManager, splitName, label, invokingMethodName)) { - log.info(INFO_3); + log.info(IMPRESSION_QUEUEING); queue.push({ feature: splitName, keyName: matchingKey, diff --git a/src/sdkClient/sdkClientMethod.ts b/src/sdkClient/sdkClientMethod.ts index 9498d0f0..82d37435 100644 --- a/src/sdkClient/sdkClientMethod.ts +++ b/src/sdkClient/sdkClientMethod.ts @@ -1,7 +1,7 @@ import { ISdkClientFactoryParams } from './types'; import { SplitIO } from '../types'; import { sdkClientFactory } from './sdkClient'; -import { DEBUG_32 } from '../logger/constants'; +import { RETRIEVE_CLIENT_DEFAULT } from '../logger/constants'; /** * Factory of client method for server-side SDKs (ISDK and IAsyncSDK) @@ -15,7 +15,7 @@ export function sdkClientMethodFactory(params: ISdkClientFactoryParams): () => S throw new Error('Shared Client not supported by the storage mechanism. Create isolated instances instead.'); } - log.debug(DEBUG_32); + log.debug(RETRIEVE_CLIENT_DEFAULT); return clientInstance; }; } diff --git a/src/sdkClient/sdkClientMethodCS.ts b/src/sdkClient/sdkClientMethodCS.ts index 28ae2ac9..80089705 100644 --- a/src/sdkClient/sdkClientMethodCS.ts +++ b/src/sdkClient/sdkClientMethodCS.ts @@ -7,7 +7,7 @@ import { sdkClientFactory } from './sdkClient'; import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; -import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/constants'; +import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING } from '../logger/constants'; function buildInstanceId(key: SplitIO.SplitKey) { // @ts-ignore @@ -42,7 +42,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? return function client(key?: SplitIO.SplitKey) { if (key === undefined) { - log.debug(DEBUG_32); + log.debug(RETRIEVE_CLIENT_DEFAULT); return mainClientInstance; } @@ -76,9 +76,9 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? sharedSyncManager.start(); - log.info(INFO_4); + log.info(NEW_SHARED_CLIENT); } else { - log.debug(DEBUG_33); + log.debug(RETRIEVE_CLIENT_EXISTING); } return clientInstances[instanceId]; diff --git a/src/sdkClient/sdkClientMethodCSWithTT.ts b/src/sdkClient/sdkClientMethodCSWithTT.ts index 03f9caac..684f3a5b 100644 --- a/src/sdkClient/sdkClientMethodCSWithTT.ts +++ b/src/sdkClient/sdkClientMethodCSWithTT.ts @@ -8,7 +8,7 @@ import { sdkClientFactory } from './sdkClient'; import { IStorageSyncCS } from '../storages/types'; import { ISyncManagerCS } from '../sync/types'; import objectAssign from 'object-assign'; -import { DEBUG_32, INFO_4, DEBUG_33 } from '../logger/constants'; +import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING } from '../logger/constants'; function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string) { // @ts-ignore @@ -49,7 +49,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? return function client(key?: SplitIO.SplitKey, trafficType?: string) { if (key === undefined) { - log.debug(DEBUG_32); + log.debug(RETRIEVE_CLIENT_DEFAULT); return mainClientInstance; } @@ -91,9 +91,9 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key? sharedSyncManager.start(); - log.info(INFO_4); + log.info(NEW_SHARED_CLIENT); } else { - log.debug(DEBUG_33); + log.debug(RETRIEVE_CLIENT_EXISTING); } return clientInstances[instanceId]; diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 4b80cabf..0b08ad5a 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -10,7 +10,7 @@ import { getMatching } from '../utils/key'; import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; import { createLoggerAPI } from '../logger/sdkLogger'; -import { INFO_5, INFO_6, ERROR_4 } from '../logger/constants'; +import { NEW_FACTORY, RETRIEVE_MANAGER, ERROR_MANAGER_NOT_AVAILABLE } from '../logger/constants'; /** * Modular SDK factory @@ -78,7 +78,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. syncManager && syncManager.start(); signalListener && signalListener.start(); - log.info(INFO_5); + log.info(NEW_FACTORY); return { // Split evaluation and event tracking engine @@ -87,8 +87,8 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // Manager API to explore available information // @ts-ignore manager() { - if (managerInstance) log.info(INFO_6); - else log.error(ERROR_4); + if (managerInstance) log.info(RETRIEVE_MANAGER); + else log.error(ERROR_MANAGER_NOT_AVAILABLE); return managerInstance; }, diff --git a/src/services/splitHttpClient.ts b/src/services/splitHttpClient.ts index 58a768d4..d19beb9c 100644 --- a/src/services/splitHttpClient.ts +++ b/src/services/splitHttpClient.ts @@ -3,7 +3,7 @@ import { SplitError, SplitNetworkError } from '../utils/lang/errors'; import objectAssign from 'object-assign'; import { IMetadata } from '../dtos/types'; import { ILogger } from '../logger/types'; -import { ERROR_39, ERROR_5 } from '../logger/constants'; +import { ERROR_HTTP, ERROR_CLIENT_CANNOT_GET_READY } from '../logger/constants'; const messageNoFetch = 'Global fetch API is not available.'; @@ -21,7 +21,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I const fetch = getFetch && getFetch(); // if fetch is not available, log Error - if (!fetch) log.error(ERROR_5, [messageNoFetch]); + if (!fetch) log.error(ERROR_CLIENT_CANNOT_GET_READY, [messageNoFetch]); const headers: Record = { 'Accept': 'application/json', @@ -66,7 +66,7 @@ export function splitHttpClientFactory(log: ILogger, apikey: string, metadata: I } if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else. - log[logErrorsAsInfo ? 'info' : 'error'](ERROR_39, [resp ? resp.status : 'NO_STATUS', url, msg]); + log[logErrorsAsInfo ? 'info' : 'error'](ERROR_HTTP, [resp ? resp.status : 'NO_STATUS', url, msg]); } // passes `undefined` as statusCode if not an HTTP error (resp === undefined) diff --git a/src/sync/offline/syncTasks/fromObjectSyncTask.ts b/src/sync/offline/syncTasks/fromObjectSyncTask.ts index a3ad3273..66c51db1 100644 --- a/src/sync/offline/syncTasks/fromObjectSyncTask.ts +++ b/src/sync/offline/syncTasks/fromObjectSyncTask.ts @@ -8,7 +8,7 @@ import { ISyncTask } from '../../types'; import { ISettings } from '../../../types'; import { CONTROL } from '../../../utils/constants'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; -import { DEBUG_36, ERROR_7 } from '../../../logger/constants'; +import { SYNC_OFFLINE_DATA, ERROR_SYNC_OFFLINE_LOADING } from '../../../logger/constants'; /** * Offline equivalent of `splitChangesUpdaterFactory` @@ -30,11 +30,11 @@ export function fromObjectUpdaterFactory( splitsMock = splitsParser(settings); } catch (err) { loadError = err; - log.error(ERROR_7, [err]); + log.error(ERROR_SYNC_OFFLINE_LOADING, [err]); } if (!loadError && splitsMock) { - log.debug(DEBUG_36, [JSON.stringify(splitsMock)]); + log.debug(SYNC_OFFLINE_DATA, [JSON.stringify(splitsMock)]); forOwn(splitsMock, function (val, name) { splits.push([ diff --git a/src/sync/polling/pollingManagerCS.ts b/src/sync/polling/pollingManagerCS.ts index 3d4687c2..7fbbc747 100644 --- a/src/sync/polling/pollingManagerCS.ts +++ b/src/sync/polling/pollingManagerCS.ts @@ -8,7 +8,7 @@ import splitsSyncTaskFactory from './syncTasks/splitsSyncTask'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants'; -import { INFO_7, INFO_8, INFO_9 } from '../../logger/constants'; +import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger/constants'; /** * Expose start / stop mechanism for polling data from services. @@ -48,7 +48,7 @@ export default function pollingManagerCSFactory( if (!splitsSyncTask.isRunning()) return; // noop if not doing polling const splitsHaveSegments = storage.splits.usesSegments(); if (splitsHaveSegments !== mySegmentsSyncTask.isRunning()) { - log.info(INFO_7, [splitsHaveSegments ? 'ON' : 'OFF']); + log.info(POLLING_SMART_PAUSING, [splitsHaveSegments ? 'ON' : 'OFF']); if (splitsHaveSegments) { startMySegmentsSyncTasks(); } else { @@ -77,7 +77,7 @@ export default function pollingManagerCSFactory( // Start periodic fetching (polling) start() { - log.info(INFO_8); + log.info(POLLING_START); splitsSyncTask.start(); if (storage.splits.usesSegments()) startMySegmentsSyncTasks(); @@ -85,7 +85,7 @@ export default function pollingManagerCSFactory( // Stop periodic fetching (polling) stop() { - log.info(INFO_9); + log.info(POLLING_STOP); if (splitsSyncTask.isRunning()) splitsSyncTask.stop(); stopMySegmentsSyncTasks(); diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index f6cf4396..24b27600 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -6,7 +6,7 @@ import { ISplitApi } from '../../services/types'; import { ISettings } from '../../types'; import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types'; import thenable from '../../utils/promise/thenable'; -import { INFO_8, INFO_9, SYNC_POLLING_LB } from '../../logger/constants'; +import { POLLING_START, POLLING_STOP, logPrefixSyncPolling } from '../../logger/constants'; /** * Expose start / stop mechanism for pulling data from services. @@ -29,9 +29,9 @@ export default function pollingManagerSSFactory( // Start periodic fetching (polling) start() { - log.info(INFO_8); - log.debug(SYNC_POLLING_LB + `Splits will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`); - log.debug(SYNC_POLLING_LB + `Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`); + log.info(POLLING_START); + log.debug(logPrefixSyncPolling + `Splits will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`); + log.debug(logPrefixSyncPolling + `Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`); const startingUp = splitsSyncTask.start(); if (thenable(startingUp)) { @@ -43,7 +43,7 @@ export default function pollingManagerSSFactory( // Stop periodic fetching (polling) stop() { - log.info(INFO_9); + log.info(POLLING_STOP); if (splitsSyncTask.isRunning()) splitsSyncTask.stop(); if (segmentsSyncTask.isRunning()) segmentsSyncTask.stop(); diff --git a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts index 9bc3aeb8..6b19166d 100644 --- a/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/mySegmentsSyncTask.ts @@ -10,7 +10,7 @@ import mySegmentsFetcherFactory from '../fetchers/mySegmentsFetcher'; import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; -import { WARN_4 } from '../../../logger/constants'; +import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants'; type IMySegmentsUpdater = (segmentList?: string[], noCache?: boolean) => Promise @@ -74,7 +74,7 @@ function mySegmentsUpdaterFactory( if (startingUp && retriesOnFailureBeforeReady > retry) { retry += 1; - log.warn(WARN_4, [retry, error]); + log.warn(SYNC_MYSEGMENTS_FETCH_RETRY, [retry, error]); return _mySegmentsUpdater(retry); // no need to forward `segmentList` and `noCache` params } else { startingUp = false; diff --git a/src/sync/polling/syncTasks/segmentsSyncTask.ts b/src/sync/polling/syncTasks/segmentsSyncTask.ts index bf131d5c..4d0d400b 100644 --- a/src/sync/polling/syncTasks/segmentsSyncTask.ts +++ b/src/sync/polling/syncTasks/segmentsSyncTask.ts @@ -11,7 +11,7 @@ import { IFetchSegmentChanges } from '../../../services/types'; import { ISettings } from '../../../types'; import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; -import { INSTANTIATION_LB, SYNC_SEGMENTS_LB } from '../../../logger/constants'; +import { logPrefixInstantiation, logPrefixSyncSegments } from '../../../logger/constants'; type ISegmentChangesUpdater = (segmentNames?: string[], noCache?: boolean, fetchOnlyNew?: boolean) => Promise @@ -48,7 +48,7 @@ function segmentChangesUpdaterFactory( * This param is used by SplitUpdateWorker on server-side SDK, to fetch new registered segments on SPLIT_UPDATE notifications. */ return function segmentChangesUpdater(segmentNames?: string[], noCache?: boolean, fetchOnlyNew?: boolean) { - log.debug(SYNC_SEGMENTS_LB + 'Started segments update'); + log.debug(logPrefixSyncSegments + 'Started segments update'); // If not a segment name provided, read list of available segments names to be updated. let segments = segmentNames ? segmentNames : segmentsCache.getRegisteredSegments(); @@ -61,7 +61,7 @@ function segmentChangesUpdaterFactory( const segmentName = segments[index]; const since = segmentsCache.getChangeNumber(segmentName); - log.debug(SYNC_SEGMENTS_LB + `Processing segment ${segmentName}`); + log.debug(logPrefixSyncSegments + `Processing segment ${segmentName}`); updaters.push(segmentChangesFetcher(since, segmentName, noCache, _promiseDecorator).then(function (changes) { let changeNumber = -1; @@ -73,7 +73,7 @@ function segmentChangesUpdaterFactory( changeNumber = x.till; } - log.debug(SYNC_SEGMENTS_LB + `Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`); + log.debug(logPrefixSyncSegments + `Processed ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`); }); return changeNumber; @@ -97,7 +97,7 @@ function segmentChangesUpdaterFactory( if (error.statusCode === 403) { // @TODO although factory status is destroyed, synchronization is not stopped readiness.destroy(); - log.error(INSTANTIATION_LB + ': you passed a client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.'); + log.error(logPrefixInstantiation + ': you passed a client-side type authorizationKey, please grab an Api Key from the Split web console that is of type Server-side.'); } return false; diff --git a/src/sync/polling/syncTasks/splitsSyncTask.ts b/src/sync/polling/syncTasks/splitsSyncTask.ts index 81bd23fc..a69e579a 100644 --- a/src/sync/polling/syncTasks/splitsSyncTask.ts +++ b/src/sync/polling/syncTasks/splitsSyncTask.ts @@ -13,7 +13,7 @@ import thenable from '../../../utils/promise/thenable'; import { ISettings } from '../../../types'; import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants'; import { ILogger } from '../../../logger/types'; -import { DEBUG_42, DEBUG_43, DEBUG_44, DEBUG_45, WARN_5, INFO_10 } from '../../../logger/constants'; +import { SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants'; type ISplitChangesUpdater = (noCache?: boolean) => Promise @@ -116,7 +116,7 @@ export function splitChangesUpdaterFactory( * @param {number} retry current number of retry attemps */ function _splitChangesUpdater(since: number, retry = 0): Promise { - log.debug(DEBUG_42, [since]); + log.debug(SYNC_SPLITS_FETCH, [since]); const fetcherPromise = splitChangesFetcher(since, noCache, _promiseDecorator) .then((splitChanges: ISplitChangesResponse) => { @@ -124,9 +124,9 @@ export function splitChangesUpdaterFactory( const mutation = computeSplitsMutation(splitChanges.splits); - log.debug(DEBUG_43, [mutation.added.length]); - log.debug(DEBUG_44, [mutation.removed.length]); - log.debug(DEBUG_45, [mutation.segments.length]); + log.debug(SYNC_SPLITS_NEW, [mutation.added.length]); + log.debug(SYNC_SPLITS_REMOVED, [mutation.removed.length]); + log.debug(SYNC_SPLITS_SEGMENTS, [mutation.segments.length]); // Write into storage // @TODO if allowing custom storages, wrap errors as SplitErrors to distinguish from user callback errors @@ -152,11 +152,11 @@ export function splitChangesUpdaterFactory( startingUp = false; // Stop retrying. } - log.warn(WARN_5, [error]); + log.warn(SYNC_SPLITS_FETCH_FAILS, [error]); if (startingUp && retriesOnFailureBeforeReady > retry) { retry += 1; - log.info(INFO_10, [retry, error]); + log.info(SYNC_SPLITS_FETCH_RETRY, [retry, error]); return _splitChangesUpdater(since, retry); } else { startingUp = false; diff --git a/src/sync/streaming/SSEHandler/index.ts b/src/sync/streaming/SSEHandler/index.ts index c1e5d5dc..716564d8 100644 --- a/src/sync/streaming/SSEHandler/index.ts +++ b/src/sync/streaming/SSEHandler/index.ts @@ -5,7 +5,7 @@ import { IPushEventEmitter } from '../types'; import { ISseEventHandler } from '../SSEClient/types'; import { INotificationError } from './types'; import { ILogger } from '../../../logger/types'; -import { WARN_6, ERROR_9, WARN_7, DEBUG_46 } from '../../../logger/constants'; +import { STREAMING_PARSING_ERROR_FAILS, ERROR_STREAMING_SSE, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_NEW_MESSAGE } from '../../../logger/constants'; function isRetryableError(error: INotificationError) { if (error.parsedData && error.parsedData.code) { @@ -40,11 +40,11 @@ export default function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventE try { errorWithParsedData = errorParser(error); } catch (err) { - log.warn(WARN_6, [err]); + log.warn(STREAMING_PARSING_ERROR_FAILS, [err]); } let errorMessage = errorWithParsedData.parsedData && errorWithParsedData.parsedData.message; - log.error(ERROR_9, [errorMessage]); + log.error(ERROR_STREAMING_SSE, [errorMessage]); if (isRetryableError(errorWithParsedData)) { pushEmitter.emit(PUSH_RETRYABLE_ERROR); @@ -59,12 +59,12 @@ export default function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventE try { messageWithParsedData = messageParser(message); } catch (err) { - log.warn(WARN_7, [err]); + log.warn(STREAMING_PARSING_MESSAGE_FAILS, [err]); return; } const { parsedData, data, channel, timestamp } = messageWithParsedData; - log.debug(DEBUG_46, [data]); + log.debug(STREAMING_NEW_MESSAGE, [data]); // we only handle update events if streaming is up. if (!notificationKeeper.isStreamingUp() && parsedData.type !== OCCUPANCY && parsedData.type !== CONTROL) diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index a3e9ef22..0e7f1559 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -18,7 +18,7 @@ import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { MY_SEGMENTS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP } from './constants'; import { IPlatform } from '../../sdkFactory/types'; -import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; +import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT } from '../../logger/constants'; /** * PushManager factory: @@ -40,7 +40,7 @@ export default function pushManagerFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(WARN_8, [e]); + log.warn(STREAMING_FALLBACK, [e]); return; } const authenticate = authenticateFactory(fetchAuth); @@ -88,14 +88,14 @@ export default function pushManagerFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(INFO_11, [delayInSeconds]); + log.info(STREAMING_REFRESH_TOKEN, [delayInSeconds]); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info(INFO_13); + log.info(STREAMING_CONNECTING); const userKeys = userKey ? Object.keys(workers) : undefined; authenticate(userKeys).then( @@ -105,7 +105,7 @@ export default function pushManagerFactory( // 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to // close the sseClient in case the org has been bloqued while the instance was connected to streaming if (!authData.pushEnabled) { - log.info(INFO_14); + log.info(STREAMING_DISABLED); pushEmitter.emit(PUSH_NONRETRYABLE_ERROR); return; } @@ -122,7 +122,7 @@ export default function pushManagerFactory( function (error) { if (disconnected) return; - log.error(ERROR_10, [error.message]); + log.error(ERROR_STREAMING_AUTH, [error.message]); // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { @@ -139,7 +139,7 @@ export default function pushManagerFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info(INFO_15); + log.info(STREAMING_DISCONNECTING); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -177,7 +177,7 @@ export default function pushManagerFactory( // retry streaming reconnect with backoff algorithm let delayInMillis = connectPushRetryBackoff.scheduleCall(); - log.info(INFO_12, [delayInMillis / 1000]); + log.info(STREAMING_RECONNECT, [delayInMillis / 1000]); pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerCS.ts b/src/sync/streaming/pushManagerCS.ts index 9a23a9ab..5611eaa0 100644 --- a/src/sync/streaming/pushManagerCS.ts +++ b/src/sync/streaming/pushManagerCS.ts @@ -17,7 +17,7 @@ import { IFetchAuth } from '../../services/types'; import { ISettings } from '../../types'; import { getMatching } from '../../utils/key'; import { IPlatform } from '../../sdkFactory/types'; -import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; +import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT } from '../../logger/constants'; /** * PushManager factory for client-side, with support for multiple clients. @@ -38,7 +38,7 @@ export default function pushManagerCSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(WARN_8, [e]); + log.warn(STREAMING_FALLBACK, [e]); return; } const authenticate = authenticateFactory(fetchAuth); @@ -84,14 +84,14 @@ export default function pushManagerCSFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(INFO_11, [delayInSeconds]); + log.info(STREAMING_REFRESH_TOKEN, [delayInSeconds]); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info(INFO_13); + log.info(STREAMING_CONNECTING); const userKeys = Object.keys(workers); // [Only for client-side] authenticate(userKeys).then( @@ -101,7 +101,7 @@ export default function pushManagerCSFactory( // 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to // close the sseClient in case the org has been bloqued while the instance was connected to streaming if (!authData.pushEnabled) { - log.info(INFO_14); + log.info(STREAMING_DISABLED); pushEmitter.emit(PUSH_NONRETRYABLE_ERROR); return; } @@ -118,7 +118,7 @@ export default function pushManagerCSFactory( function (error) { if (disconnected) return; - log.error(ERROR_10, [error.message]); + log.error(ERROR_STREAMING_AUTH, [error.message]); // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { @@ -135,7 +135,7 @@ export default function pushManagerCSFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info(INFO_15); + log.info(STREAMING_DISCONNECTING); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -172,7 +172,7 @@ export default function pushManagerCSFactory( // retry streaming reconnect with backoff algorithm let delayInMillis = connectPushRetryBackoff.scheduleCall(); - log.info(INFO_12, [delayInMillis / 1000]); + log.info(STREAMING_RECONNECT, [delayInMillis / 1000]); pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already }); diff --git a/src/sync/streaming/pushManagerSS.ts b/src/sync/streaming/pushManagerSS.ts index 138a52e9..37de7fce 100644 --- a/src/sync/streaming/pushManagerSS.ts +++ b/src/sync/streaming/pushManagerSS.ts @@ -14,7 +14,7 @@ import { authenticateFactory } from './AuthClient'; import SSEClient from './SSEClient'; import { ISettings } from '../../types'; import { IPlatform } from '../../sdkFactory/types'; -import { WARN_8, INFO_11, INFO_13, INFO_14, ERROR_10, INFO_15, INFO_12 } from '../../logger/constants'; +import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT } from '../../logger/constants'; /** * PushManager factory for server-side @@ -34,7 +34,7 @@ export default function pushManagerSSFactory( try { sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource); } catch (e) { - log.warn(WARN_8, [e]); + log.warn(STREAMING_FALLBACK, [e]); return; } const authenticate = authenticateFactory(fetchAuth); @@ -65,14 +65,14 @@ export default function pushManagerSSFactory( // Set token refresh 10 minutes before expirationTime const delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION; - log.info(INFO_11, [delayInSeconds]); + log.info(STREAMING_REFRESH_TOKEN, [delayInSeconds]); timeoutId = setTimeout(connectPush, delayInSeconds * 1000); } function connectPush() { disconnected = false; - log.info(INFO_13); + log.info(STREAMING_CONNECTING); authenticate().then( function (authData) { @@ -81,7 +81,7 @@ export default function pushManagerSSFactory( // 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to // close the sseClient in case the org has been bloqued while the instance was connected to streaming if (!authData.pushEnabled) { - log.info(INFO_14); + log.info(STREAMING_DISABLED); pushEmitter.emit(PUSH_NONRETRYABLE_ERROR); return; } @@ -95,7 +95,7 @@ export default function pushManagerSSFactory( function (error) { if (disconnected) return; - log.error(ERROR_10, [error.message]); + log.error(ERROR_STREAMING_AUTH, [error.message]); // Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side) if (error.statusCode >= 400 && error.statusCode < 500) { @@ -112,7 +112,7 @@ export default function pushManagerSSFactory( // close SSE connection and cancel scheduled tasks function disconnectPush() { disconnected = true; - log.info(INFO_15); + log.info(STREAMING_DISCONNECTING); sseClient.close(); if (timeoutId) clearTimeout(timeoutId); @@ -149,7 +149,7 @@ export default function pushManagerSSFactory( // retry streaming reconnect with backoff algorithm let delayInMillis = connectPushRetryBackoff.scheduleCall(); - log.info(INFO_12, [delayInMillis / 1000]); + log.info(STREAMING_RECONNECT, [delayInMillis / 1000]); pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already }); diff --git a/src/sync/submitters/eventsSyncTask.ts b/src/sync/submitters/eventsSyncTask.ts index e7024c0c..3a15a6e0 100644 --- a/src/sync/submitters/eventsSyncTask.ts +++ b/src/sync/submitters/eventsSyncTask.ts @@ -3,7 +3,7 @@ import { IPostEventsBulk } from '../../services/types'; import { ISyncTask, ITimeTracker } from '../types'; import { submitterSyncTaskFactory } from './submitterSyncTask'; import { ILogger } from '../../logger/types'; -import { INFO_16 } from '../../logger/constants'; +import { SUBMITTERS_PUSH_FULL_EVENTS_QUEUE } from '../../logger/constants'; /** * Sync task that periodically posts tracked events @@ -36,7 +36,7 @@ export function eventsSyncTaskFactory( // register eventsSubmitter to be executed when events cache is full eventsCache.setOnFullQueueCb(() => { - log.info(INFO_16); + log.info(SUBMITTERS_PUSH_FULL_EVENTS_QUEUE); syncTask.execute(); }); diff --git a/src/sync/submitters/submitterSyncTask.ts b/src/sync/submitters/submitterSyncTask.ts index da6a9301..cbee1913 100644 --- a/src/sync/submitters/submitterSyncTask.ts +++ b/src/sync/submitters/submitterSyncTask.ts @@ -2,7 +2,7 @@ import syncTaskFactory from '../syncTask'; import { ISyncTask, ITimeTracker } from '../types'; import { IRecorderCacheConsumerSync } from '../../storages/types'; import { ILogger } from '../../logger/types'; -import { INFO_17, WARN_9, WARN_10 } from '../../logger/constants'; +import { SUBMITTERS_PUSH, SUBMITTERS_PUSH_FAILS, SUBMITTERS_PUSH_RETRY } from '../../logger/constants'; /** * Base function to create submitter sync tasks, such as ImpressionsSyncTask and EventsSyncTask @@ -26,7 +26,7 @@ export function submitterSyncTaskFactory( const data = sourceCache.state(); const dataCount: number | '' = typeof data.length === 'number' ? data.length : ''; - log.info(INFO_17, [dataCount, dataName]); + log.info(SUBMITTERS_PUSH, [dataCount, dataName]); const latencyTrackerStop = latencyTracker && latencyTracker.start(); const jsonPayload = JSON.stringify(fromCacheToPayload ? fromCacheToPayload(data) : data); @@ -37,14 +37,14 @@ export function submitterSyncTaskFactory( sourceCache.clear(); // we clear the queue if request successes. }).catch(err => { if (!maxRetries) { - log.warn(WARN_9, [dataCount, dataName, err]); + log.warn(SUBMITTERS_PUSH_FAILS, [dataCount, dataName, err]); } else if (retries === maxRetries) { retries = 0; sourceCache.clear(); // we clear the queue if request fails after retries. - log.warn(WARN_9, [dataCount, dataName, err]); + log.warn(SUBMITTERS_PUSH_FAILS, [dataCount, dataName, err]); } else { retries++; - log.warn(WARN_10, [dataCount, dataName, err]); + log.warn(SUBMITTERS_PUSH_RETRY, [dataCount, dataName, err]); } }); diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index 4a0a0099..04a0c98f 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -8,7 +8,7 @@ import { IStorageSync } from '../storages/types'; import { IPushManagerFactoryParams, IPushManager, IPushManagerCS } from './streaming/types'; import { IPollingManager, IPollingManagerCS, IPollingManagerFactoryParams } from './polling/types'; import { PUSH_SUBSYSTEM_UP, PUSH_SUBSYSTEM_DOWN } from './streaming/constants'; -import { INFO_18, INFO_19, INFO_20 } from '../logger/constants'; +import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '../logger/constants'; /** * Online SyncManager factory. @@ -59,15 +59,15 @@ export function syncManagerOnlineFactory( function startPolling() { if (!pollingManager.isRunning()) { - log.info(INFO_18); + log.info(SYNC_START_POLLING); pollingManager.start(); } else { - log.info(INFO_19); + log.info(SYNC_CONTINUE_POLLING); } } function stopPollingAndSyncAll() { - log.info(INFO_20); + log.info(SYNC_STOP_POLLING); // if polling, stop if (pollingManager.isRunning()) pollingManager.stop(); diff --git a/src/sync/syncTask.ts b/src/sync/syncTask.ts index cb63701c..321ea99e 100644 --- a/src/sync/syncTask.ts +++ b/src/sync/syncTask.ts @@ -1,4 +1,4 @@ -import { DEBUG_48, DEBUG_47, DEBUG_49 } from '../logger/constants'; +import { SYNC_TASK_EXECUTE, SYNC_TASK_START, SYNC_TASK_STOP } from '../logger/constants'; import { ILogger } from '../logger/types'; import { ISyncTask } from './types'; @@ -16,7 +16,7 @@ export default function syncTaskFactory(log: ILogge function execute(...args: Input) { executing = true; - log.debug(DEBUG_48, [taskName]); + log.debug(SYNC_TASK_EXECUTE, [taskName]); return task(...args).then(result => { executing = false; if (running) timeoutID = setTimeout(execute, period, ...args); @@ -34,7 +34,7 @@ export default function syncTaskFactory(log: ILogge start(...args: Input) { if (!running) { running = true; - log.debug(DEBUG_47, [taskName, period]); + log.debug(SYNC_TASK_START, [taskName, period]); return execute(...args); } }, @@ -42,7 +42,7 @@ export default function syncTaskFactory(log: ILogge stop() { running = false; if (timeoutID) { - log.debug(DEBUG_49, [taskName]); + log.debug(SYNC_TASK_STOP, [taskName]); clearTimeout(timeoutID); timeoutID = undefined; } diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index 960924dc..343e737f 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -4,7 +4,7 @@ import { IEventsCacheBase } from '../storages/types'; import { IEventsHandler, IEventTracker } from './types'; import { SplitIO } from '../types'; import { ILogger } from '../logger/types'; -import { INFO_21, WARN_11 } from '../logger/constants'; +import { EVENTS_TRACKER_SUCCESS, ERROR_EVENTS_TRACKER } from '../logger/constants'; /** * Event tracker stores events in cache and pass them to the integrations manager if provided. @@ -24,7 +24,7 @@ export default function eventTrackerFactory( const msg = `event of type "${eventTypeId}" for traffic type "${trafficTypeName}". Key: ${key}. Value: ${value}. Timestamp: ${timestamp}. ${properties ? 'With properties.' : 'With no properties.'}`; if (tracked) { - log.info(INFO_21, [msg]); + log.info(EVENTS_TRACKER_SUCCESS, [msg]); if (integrationsManager) { // Wrap in a timeout because we don't want it to be blocking. setTimeout(function () { @@ -36,7 +36,7 @@ export default function eventTrackerFactory( }, 0); } } else { - log.warn(WARN_11, [msg]); + log.warn(ERROR_EVENTS_TRACKER, [msg]); } return tracked; diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index 53ec5178..00e7c25f 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -7,7 +7,7 @@ import { IMetadata } from '../dtos/types'; import { SplitIO, ImpressionDTO } from '../types'; import { IImpressionObserver } from './impressionObserver/types'; import { ILogger } from '../logger/types'; -import { DEBUG_50, ERROR_11, ERROR_12 } from '../logger/constants'; +import { IMPRESSIONS_TRACKER_SUCCESS, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER } from '../logger/constants'; /** * Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided. @@ -63,9 +63,9 @@ export default function impressionsTrackerFactory( // If we're on an async storage, handle error and log it. if (thenable(res)) { res.then(() => { - log.debug(DEBUG_50, [impressionsCount, impressionsCount === 1 ? '' : 's']); + log.debug(IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount, impressionsCount === 1 ? '' : 's']); }).catch(err => { - log.error(ERROR_11, [impressionsCount, impressionsCount === 1 ? '' : 's', err]); + log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsCount, impressionsCount === 1 ? '' : 's', err]); }); } @@ -89,7 +89,7 @@ export default function impressionsTrackerFactory( try { // An exception on the listeners should not break the SDK. if (impressionListener) impressionListener.logImpression(impressionData); } catch (err) { - log.error(ERROR_12, [err]); + log.error(ERROR_IMPRESSIONS_LISTENER, [err]); } }, 0); } diff --git a/src/utils/inputValidation/__tests__/isOperational.spec.ts b/src/utils/inputValidation/__tests__/isOperational.spec.ts index 0d32547a..f78afb51 100644 --- a/src/utils/inputValidation/__tests__/isOperational.spec.ts +++ b/src/utils/inputValidation/__tests__/isOperational.spec.ts @@ -1,4 +1,4 @@ -import { WARN_CLIENT_NOT_READY, ERROR_CLIENT_DESTROYED } from '../../../logger/constants'; +import { CLIENT_NOT_READY, ERROR_CLIENT_DESTROYED } from '../../../logger/constants'; import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; import { validateIfNotDestroyed, validateIfOperational } from '../isOperational'; @@ -58,7 +58,7 @@ describe('validateIfOperational', () => { expect(validateIfOperational(loggerMock, readinessManagerMock, 'test_method')).toBe(false); // It should return true if SDK was ready. expect(readinessManagerMock.isReady).toBeCalledTimes(1); // It checks for SDK_READY status. expect(readinessManagerMock.isReadyFromCache).toBeCalledTimes(1); // It checks for SDK_READY_FROM_CACHE status. - expect(loggerMock.warn).toBeCalledWith(WARN_CLIENT_NOT_READY, ['test_method']); // It should log the expected warning. + expect(loggerMock.warn).toBeCalledWith(CLIENT_NOT_READY, ['test_method']); // It should log the expected warning. expect(loggerMock.error).not.toBeCalled(); // But it should not log any errors. }); }); diff --git a/src/utils/inputValidation/apiKey.ts b/src/utils/inputValidation/apiKey.ts index a629815a..0b891abf 100644 --- a/src/utils/inputValidation/apiKey.ts +++ b/src/utils/inputValidation/apiKey.ts @@ -1,4 +1,4 @@ -import { ERROR_NULL, ERROR_EMPTY, ERROR_INVALID, WARN_API_KEY, INSTANTIATION_LB } from '../../logger/constants'; +import { ERROR_NULL, ERROR_EMPTY, ERROR_INVALID, WARN_API_KEY, logPrefixInstantiation } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { isString } from '../lang'; @@ -8,14 +8,14 @@ const item = 'api_key'; export function validateApiKey(log: ILogger, maybeApiKey: any): string | false { let apiKey: string | false = false; if (maybeApiKey == undefined) { // eslint-disable-line eqeqeq - log.error(ERROR_NULL, [INSTANTIATION_LB, item]); + log.error(ERROR_NULL, [logPrefixInstantiation, item]); } else if (isString(maybeApiKey)) { if (maybeApiKey.length > 0) apiKey = maybeApiKey; else - log.error(ERROR_EMPTY, [INSTANTIATION_LB, item]); + log.error(ERROR_EMPTY, [logPrefixInstantiation, item]); } else { - log.error(ERROR_INVALID, [INSTANTIATION_LB, item]); + log.error(ERROR_INVALID, [logPrefixInstantiation, item]); } return apiKey; diff --git a/src/utils/inputValidation/isOperational.ts b/src/utils/inputValidation/isOperational.ts index 666b9d33..05ad0aad 100644 --- a/src/utils/inputValidation/isOperational.ts +++ b/src/utils/inputValidation/isOperational.ts @@ -1,4 +1,4 @@ -import { ERROR_CLIENT_DESTROYED, WARN_CLIENT_NOT_READY } from '../../logger/constants'; +import { ERROR_CLIENT_DESTROYED, CLIENT_NOT_READY } from '../../logger/constants'; import { ILogger } from '../../logger/types'; import { IReadinessManager } from '../../readiness/types'; @@ -12,6 +12,6 @@ export function validateIfNotDestroyed(log: ILogger, readinessManager: IReadines export function validateIfOperational(log: ILogger, readinessManager: IReadinessManager, method: string) { if (readinessManager.isReady() || readinessManager.isReadyFromCache()) return true; - log.warn(WARN_CLIENT_NOT_READY, [method]); + log.warn(CLIENT_NOT_READY, [method]); return false; } diff --git a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts index 6024ec2e..3aa994dd 100644 --- a/src/utils/settingsValidation/__tests__/splitFilters.spec.ts +++ b/src/utils/settingsValidation/__tests__/splitFilters.spec.ts @@ -7,7 +7,7 @@ import { splitFilters, queryStrings, groupedFilters } from '../../../__tests__/m // Test target import { validateSplitFilters } from '../splitFilters'; -import { DEBUG_SPLITS_FILTER, ERROR_INVALID, ERROR_EMPTY_ARRAY, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY } from '../../../logger/constants'; +import { SETTINGS_SPLITS_FILTER, ERROR_INVALID, ERROR_EMPTY_ARRAY, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY } from '../../../logger/constants'; describe('validateSplitFilters', () => { @@ -48,7 +48,7 @@ describe('validateSplitFilters', () => { groupedFilters: { byName: [], byPrefix: [] } }; expect(validateSplitFilters(loggerMock, splitFilters, STANDALONE_MODE)).toEqual(output); // filters without values - expect(loggerMock.debug).toBeCalledWith(DEBUG_SPLITS_FILTER, [null]); + expect(loggerMock.debug).toBeCalledWith(SETTINGS_SPLITS_FILTER, [null]); loggerMock.debug.mockClear(); splitFilters.push( @@ -58,7 +58,7 @@ describe('validateSplitFilters', () => { { type: 'byName', values: [13] }); output.validFilters.push({ type: 'byName', values: [13] }); expect(validateSplitFilters(loggerMock, splitFilters, STANDALONE_MODE)).toEqual(output); // some filters are invalid - expect(loggerMock.debug.mock.calls).toEqual([[DEBUG_SPLITS_FILTER, [null]]]); + expect(loggerMock.debug.mock.calls).toEqual([[SETTINGS_SPLITS_FILTER, [null]]]); expect(loggerMock.warn.mock.calls).toEqual([ [WARN_SPLITS_FILTER_INVALID, [3]], // invalid value of `type` property [WARN_SPLITS_FILTER_INVALID, [4]], // invalid type of `values` property @@ -82,7 +82,7 @@ describe('validateSplitFilters', () => { groupedFilters: groupedFilters[i] }; expect(validateSplitFilters(loggerMock, splitFilters[i], STANDALONE_MODE)).toEqual(output); // splitFilters #${i} - expect(loggerMock.debug).lastCalledWith(DEBUG_SPLITS_FILTER, [queryStrings[i]]); + expect(loggerMock.debug).lastCalledWith(SETTINGS_SPLITS_FILTER, [queryStrings[i]]); } else { // tests where validateSplitFilters throws an exception expect(() => validateSplitFilters(loggerMock, splitFilters[i], STANDALONE_MODE)).toThrow(queryStrings[i]); diff --git a/src/utils/settingsValidation/logger/pluggableLogger.ts b/src/utils/settingsValidation/logger/pluggableLogger.ts index 90746543..7b149990 100644 --- a/src/utils/settingsValidation/logger/pluggableLogger.ts +++ b/src/utils/settingsValidation/logger/pluggableLogger.ts @@ -28,7 +28,7 @@ export function validateLogger(settings: { debug: unknown }): ILogger { const log = new Logger({ logLevel: logLevel || initialLogLevel }); - // @ts-ignore // if logLevel is undefined at this point, it means that `debug` value is invalid + // @ts-ignore // `debug` value is invalid if logLevel is undefined at this point if (!logLevel) log._log(LogLevels.ERROR, 'Invalid `debug` value at config. Logs will be disabled.'); return log; diff --git a/src/utils/settingsValidation/splitFilters.ts b/src/utils/settingsValidation/splitFilters.ts index 8542a44b..7c474952 100644 --- a/src/utils/settingsValidation/splitFilters.ts +++ b/src/utils/settingsValidation/splitFilters.ts @@ -3,7 +3,7 @@ import { validateSplits } from '../inputValidation/splits'; import { ISplitFiltersValidation } from '../../dtos/types'; import { SplitIO } from '../../types'; import { ILogger } from '../../logger/types'; -import { WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_EMPTY, WARN_SPLITS_FILTER_INVALID, DEBUG_SPLITS_FILTER, SETTINGS_LB } from '../../logger/constants'; +import { WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_EMPTY, WARN_SPLITS_FILTER_INVALID, SETTINGS_SPLITS_FILTER, logPrefixSettings } from '../../logger/constants'; // Split filters metadata. // Ordered according to their precedency when forming the filter query string: `&names=&prefixes=` @@ -39,7 +39,7 @@ function validateFilterType(maybeFilterType: any): maybeFilterType is SplitIO.Sp */ function validateSplitFilter(log: ILogger, type: SplitIO.SplitFilterType, values: string[], maxLength: number) { // validate and remove invalid and duplicated values - let result = validateSplits(log, values, SETTINGS_LB, `${type} filter`, `${type} filter value`); + let result = validateSplits(log, values, logPrefixSettings, `${type} filter`, `${type} filter value`); if (result) { // check max length @@ -125,7 +125,7 @@ export function validateSplitFilters(log: ILogger, maybeSplitFilters: any, mode: // build query string res.queryString = queryStringBuilder(res.groupedFilters); - log.debug(DEBUG_SPLITS_FILTER, [res.queryString]); + log.debug(SETTINGS_SPLITS_FILTER, [res.queryString]); return res; } From 15093c9efc3c255741df012200ebafdc3bfd0303 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 25 Mar 2021 19:56:56 -0300 Subject: [PATCH 53/58] feedback --- src/evaluator/matchers/segment.ts | 4 ++-- src/logger/constants.ts | 8 +++----- src/logger/messages/debug.ts | 7 +++---- src/logger/messages/error.ts | 8 ++++---- src/logger/messages/info.ts | 5 +++-- src/logger/messages/warn.ts | 6 ++---- src/sdkFactory/index.ts | 7 +++---- src/sdkFactory/types.ts | 2 +- src/trackers/eventTracker.ts | 2 +- src/trackers/impressionsTracker.ts | 4 ++-- 10 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/evaluator/matchers/segment.ts b/src/evaluator/matchers/segment.ts index 7b6f6d4f..3e9db7d5 100644 --- a/src/evaluator/matchers/segment.ts +++ b/src/evaluator/matchers/segment.ts @@ -2,7 +2,7 @@ import { MaybeThenable } from '../../dtos/types'; import { ISegmentsCacheBase } from '../../storages/types'; import { ILogger } from '../../logger/types'; import thenable from '../../utils/promise/thenable'; -import { ENGINE_MATCHER_SEGMENT_ASYNC, ENGINE_MATCHER_SEGMENT } from '../../logger/constants'; +import { ENGINE_MATCHER_SEGMENT } from '../../logger/constants'; export default function matcherSegmentContext(log: ILogger, segmentName: string, storage: { segments: ISegmentsCacheBase }) { @@ -11,7 +11,7 @@ export default function matcherSegmentContext(log: ILogger, segmentName: string, if (thenable(isInSegment)) { isInSegment.then(result => { - log.debug(ENGINE_MATCHER_SEGMENT_ASYNC, [segmentName, key, isInSegment]); + log.debug(ENGINE_MATCHER_SEGMENT, [segmentName, key, isInSegment]); return result; }); diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 8b0c9397..75e18f7e 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -23,7 +23,6 @@ export const ENGINE_MATCHER_ENDS_WITH = 14; export const ENGINE_MATCHER_GREATER = 15; export const ENGINE_MATCHER_LESS = 16; export const ENGINE_MATCHER_PART_OF = 17; -export const ENGINE_MATCHER_SEGMENT_ASYNC = 18; export const ENGINE_MATCHER_SEGMENT = 19; export const ENGINE_MATCHER_STRING = 20; export const ENGINE_MATCHER_STRING_INVALID = 21; @@ -35,6 +34,7 @@ export const CLEANUP_REGISTERING = 26; export const CLEANUP_DEREGISTERING = 27; export const RETRIEVE_CLIENT_DEFAULT = 32; export const RETRIEVE_CLIENT_EXISTING = 33; +export const RETRIEVE_MANAGER = 34; export const SYNC_OFFLINE_DATA = 36; export const SYNC_SPLITS_FETCH = 42; export const SYNC_SPLITS_NEW = 43; @@ -44,7 +44,6 @@ export const STREAMING_NEW_MESSAGE = 46; export const SYNC_TASK_START = 47; export const SYNC_TASK_EXECUTE = 48; export const SYNC_TASK_STOP = 49; -export const IMPRESSIONS_TRACKER_SUCCESS = 50; export const SETTINGS_SPLITS_FILTER = 51; export const CLIENT_READY_FROM_CACHE = 100; @@ -53,7 +52,6 @@ export const IMPRESSION = 102; export const IMPRESSION_QUEUEING = 103; export const NEW_SHARED_CLIENT = 104; export const NEW_FACTORY = 105; -export const RETRIEVE_MANAGER = 106; export const POLLING_SMART_PAUSING = 107; export const POLLING_START = 108; export const POLLING_STOP = 109; @@ -69,6 +67,7 @@ export const SYNC_START_POLLING = 118; export const SYNC_CONTINUE_POLLING = 119; export const SYNC_STOP_POLLING = 120; export const EVENTS_TRACKER_SUCCESS = 121; +export const IMPRESSIONS_TRACKER_SUCCESS = 122; export const ENGINE_VALUE_INVALID = 200; export const ENGINE_VALUE_NO_ATTRIBUTES = 201; @@ -94,18 +93,17 @@ export const WARN_SPLITS_FILTER_INVALID = 223; export const WARN_SPLITS_FILTER_EMPTY = 224; export const WARN_STORAGE_INVALID = 225; export const WARN_API_KEY = 226; -export const ERROR_EVENTS_TRACKER = 211; export const ERROR_ENGINE_COMBINER_IFELSEIF = 300; export const ERROR_LOGLEVEL_INVALID = 302; export const ERROR_CLIENT_LISTENER = 303; -export const ERROR_MANAGER_NOT_AVAILABLE = 304; export const ERROR_CLIENT_CANNOT_GET_READY = 305; export const ERROR_SYNC_OFFLINE_LOADING = 307; export const ERROR_STREAMING_SSE = 309; export const ERROR_STREAMING_AUTH = 310; export const ERROR_IMPRESSIONS_TRACKER = 311; export const ERROR_IMPRESSIONS_LISTENER = 312; +export const ERROR_EVENTS_TRACKER = 313; export const ERROR_EVENT_TYPE_FORMAT = 314; export const ERROR_NOT_PLAIN_OBJECT = 318; export const ERROR_SIZE_EXCEEDED = 319; diff --git a/src/logger/messages/debug.ts b/src/logger/messages/debug.ts index af0098c8..9b4468ae 100644 --- a/src/logger/messages/debug.ts +++ b/src/logger/messages/debug.ts @@ -1,4 +1,4 @@ -import { ENGINE_COMBINER_AND, ENGINE_COMBINER_IFELSEIF, ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, ENGINE_BUCKET, ENGINE_MATCHER_ALL, ENGINE_MATCHER_BETWEEN, ENGINE_MATCHER_BOOLEAN, ENGINE_MATCHER_CONTAINS_ALL, ENGINE_MATCHER_CONTAINS_ANY, ENGINE_MATCHER_CONTAINS_STRING, ENGINE_MATCHER_DEPENDENCY, ENGINE_MATCHER_DEPENDENCY_PRE, ENGINE_MATCHER_EQUAL, ENGINE_MATCHER_EQUAL_TO_SET, ENGINE_MATCHER_ENDS_WITH, ENGINE_MATCHER_GREATER, ENGINE_MATCHER_LESS, ENGINE_MATCHER_PART_OF, ENGINE_MATCHER_SEGMENT_ASYNC, ENGINE_MATCHER_SEGMENT, ENGINE_MATCHER_STRING, ENGINE_MATCHER_STRING_INVALID, ENGINE_MATCHER_STARTS_WITH, ENGINE_MATCHER_WHITELIST, ENGINE_VALUE, ENGINE_SANITIZE, RETRIEVE_CLIENT_DEFAULT, RETRIEVE_CLIENT_EXISTING, SYNC_OFFLINE_DATA, SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, STREAMING_NEW_MESSAGE, SYNC_TASK_START, SYNC_TASK_EXECUTE, SYNC_TASK_STOP, IMPRESSIONS_TRACKER_SUCCESS, SETTINGS_SPLITS_FILTER, logPrefixSettings, logPrefixEngine, logPrefixEngineCombiner, logPrefixEngineMatcher, logPrefixEngineValue, logPrefixSyncOffline, logPrefixImpressionsTracker, logPrefixSync, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixCleanup, CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../constants'; +import { ENGINE_COMBINER_AND, ENGINE_COMBINER_IFELSEIF, ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, ENGINE_BUCKET, ENGINE_MATCHER_ALL, ENGINE_MATCHER_BETWEEN, ENGINE_MATCHER_BOOLEAN, ENGINE_MATCHER_CONTAINS_ALL, ENGINE_MATCHER_CONTAINS_ANY, ENGINE_MATCHER_CONTAINS_STRING, ENGINE_MATCHER_DEPENDENCY, ENGINE_MATCHER_DEPENDENCY_PRE, ENGINE_MATCHER_EQUAL, ENGINE_MATCHER_EQUAL_TO_SET, ENGINE_MATCHER_ENDS_WITH, ENGINE_MATCHER_GREATER, ENGINE_MATCHER_LESS, ENGINE_MATCHER_PART_OF, ENGINE_MATCHER_SEGMENT, ENGINE_MATCHER_STRING, ENGINE_MATCHER_STRING_INVALID, ENGINE_MATCHER_STARTS_WITH, ENGINE_MATCHER_WHITELIST, ENGINE_VALUE, ENGINE_SANITIZE, RETRIEVE_CLIENT_DEFAULT, RETRIEVE_CLIENT_EXISTING, RETRIEVE_MANAGER, SYNC_OFFLINE_DATA, SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, STREAMING_NEW_MESSAGE, SYNC_TASK_START, SYNC_TASK_EXECUTE, SYNC_TASK_STOP, SETTINGS_SPLITS_FILTER, logPrefixSettings, logPrefixEngine, logPrefixEngineCombiner, logPrefixEngineMatcher, logPrefixEngineValue, logPrefixSyncOffline, logPrefixSync, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixCleanup, CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../constants'; import { codesInfo } from './info'; export const codesDebug: [number, string][] = codesInfo.concat([ @@ -13,7 +13,7 @@ export const codesDebug: [number, string][] = codesInfo.concat([ [ENGINE_MATCHER_CONTAINS_ALL, logPrefixEngineMatcher + '[containsAllMatcher] %s contains all elements of %s? %s'], [ENGINE_MATCHER_CONTAINS_ANY, logPrefixEngineMatcher + '[containsAnyMatcher] %s contains at least an element of %s? %s'], [ENGINE_MATCHER_CONTAINS_STRING, logPrefixEngineMatcher + '[containsStringMatcher] %s contains %s? %s'], - [ENGINE_MATCHER_DEPENDENCY, logPrefixEngineMatcher + '[dependencyMatcher] Parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], + [ENGINE_MATCHER_DEPENDENCY, logPrefixEngineMatcher + '[dependencyMatcher] parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], [ENGINE_MATCHER_DEPENDENCY_PRE, logPrefixEngineMatcher + '[dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], [ENGINE_MATCHER_EQUAL, logPrefixEngineMatcher + '[equalToMatcher] is %s equal to %s? %s'], [ENGINE_MATCHER_EQUAL_TO_SET, logPrefixEngineMatcher + '[equalToSetMatcher] is %s equal to set %s? %s'], @@ -21,7 +21,6 @@ export const codesDebug: [number, string][] = codesInfo.concat([ [ENGINE_MATCHER_GREATER, logPrefixEngineMatcher + '[greaterThanEqualMatcher] is %s greater than %s? %s'], [ENGINE_MATCHER_LESS, logPrefixEngineMatcher + '[lessThanEqualMatcher] is %s less than %s? %s'], [ENGINE_MATCHER_PART_OF, logPrefixEngineMatcher + '[partOfMatcher] %s is part of %s? %s'], - [ENGINE_MATCHER_SEGMENT_ASYNC, logPrefixEngineMatcher + '[asyncSegmentMatcher] evaluated %s / %s => %s'], [ENGINE_MATCHER_SEGMENT, logPrefixEngineMatcher + '[segmentMatcher] evaluated %s / %s => %s'], [ENGINE_MATCHER_STRING, logPrefixEngineMatcher + '[stringMatcher] does %s matches with %s? %s'], [ENGINE_MATCHER_STRING_INVALID, logPrefixEngineMatcher + '[stringMatcher] %s is an invalid regex'], @@ -34,6 +33,7 @@ export const codesDebug: [number, string][] = codesInfo.concat([ [CLEANUP_DEREGISTERING, logPrefixCleanup + 'Deregistering cleanup handler %s'], [RETRIEVE_CLIENT_DEFAULT, ' Retrieving default SDK client.'], [RETRIEVE_CLIENT_EXISTING, ' Retrieving existing SDK client.'], + [RETRIEVE_MANAGER, ' Retrieving manager instance.'], // synchronizer [SYNC_OFFLINE_DATA, logPrefixSyncOffline + 'Splits data: \n%s'], [SYNC_SPLITS_FETCH, logPrefixSyncSplits + 'Spin up split update using since = %s'], @@ -44,7 +44,6 @@ export const codesDebug: [number, string][] = codesInfo.concat([ [SYNC_TASK_START, logPrefixSync + ': Starting %s. Running each %s millis'], [SYNC_TASK_EXECUTE, logPrefixSync + ': Running %s'], [SYNC_TASK_STOP, logPrefixSync + ': Stopping %s'], - [IMPRESSIONS_TRACKER_SUCCESS, logPrefixImpressionsTracker + 'Successfully stored %s impression%s.'], // initialization / settings validation [SETTINGS_SPLITS_FILTER, logPrefixSettings + ': splits filtering criteria is "%s".'] ]); diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index 54e0c188..2e4eb9c7 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -1,18 +1,18 @@ -import { ERROR_ENGINE_COMBINER_IFELSEIF, ERROR_LOGLEVEL_INVALID, ERROR_CLIENT_LISTENER, ERROR_MANAGER_NOT_AVAILABLE, ERROR_CLIENT_CANNOT_GET_READY, ERROR_SYNC_OFFLINE_LOADING, ERROR_STREAMING_SSE, ERROR_STREAMING_AUTH, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_CLIENT_DESTROYED, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_IMPRESSIONS_MODE, ERROR_HTTP, logPrefixSettings, logPrefixEngineCombiner, logPrefixSyncOffline, logPrefixSyncStreaming, logPrefixImpressionsTracker } from '../constants'; +import { ERROR_ENGINE_COMBINER_IFELSEIF, ERROR_LOGLEVEL_INVALID, ERROR_CLIENT_LISTENER, ERROR_CLIENT_CANNOT_GET_READY, ERROR_SYNC_OFFLINE_LOADING, ERROR_STREAMING_SSE, ERROR_STREAMING_AUTH, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_CLIENT_DESTROYED, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_IMPRESSIONS_MODE, ERROR_HTTP, logPrefixSettings, logPrefixEngineCombiner, logPrefixSyncOffline, logPrefixSyncStreaming, logPrefixImpressionsTracker, ERROR_EVENTS_TRACKER, logPrefixEventsTracker } from '../constants'; export const codesError: [number, string][] = [ // evaluator [ERROR_ENGINE_COMBINER_IFELSEIF, logPrefixEngineCombiner + 'Invalid Split, no valid rules found'], // SDK [ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'], - [ERROR_MANAGER_NOT_AVAILABLE, ' Manager instance is not available.'], // @TODO remove if the manager is not pluggable [ERROR_CLIENT_CANNOT_GET_READY, ' The SDK will not get ready. Reason: %s'], + [ERROR_IMPRESSIONS_TRACKER, logPrefixImpressionsTracker + 'Could not store impressions bulk with %s impression(s). Error: %s'], + [ERROR_IMPRESSIONS_LISTENER, logPrefixImpressionsTracker + 'Impression listener logImpression method threw: %s.'], + [ERROR_EVENTS_TRACKER, logPrefixEventsTracker + 'Failed to queue %s'], // synchronizer [ERROR_SYNC_OFFLINE_LOADING, logPrefixSyncOffline + 'There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], [ERROR_STREAMING_SSE, logPrefixSyncStreaming + 'Fail to connect to streaming, with error message: %s'], [ERROR_STREAMING_AUTH, logPrefixSyncStreaming + 'Failed to authenticate for streaming. Error: "%s".'], - [ERROR_IMPRESSIONS_TRACKER, logPrefixImpressionsTracker + 'Could not store impressions bulk with %s impression%s. Error: %s'], - [ERROR_IMPRESSIONS_LISTENER, logPrefixImpressionsTracker + 'Impression listener logImpression method threw: %s.'], [ERROR_HTTP, ' Response status is not OK. Status: %s. URL: %s. Message: %s'], // client status [ERROR_CLIENT_LISTENER, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], diff --git a/src/logger/messages/info.ts b/src/logger/messages/info.ts index 9a9c237e..6c00a5ff 100644 --- a/src/logger/messages/info.ts +++ b/src/logger/messages/info.ts @@ -1,4 +1,4 @@ -import { CLIENT_READY_FROM_CACHE, CLIENT_READY, IMPRESSION, IMPRESSION_QUEUEING, NEW_SHARED_CLIENT, NEW_FACTORY, RETRIEVE_MANAGER, POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP, SYNC_SPLITS_FETCH_RETRY, STREAMING_REFRESH_TOKEN, STREAMING_RECONNECT, STREAMING_CONNECTING, STREAMING_DISABLED, STREAMING_DISCONNECTING, SUBMITTERS_PUSH_FULL_EVENTS_QUEUE, SUBMITTERS_PUSH, SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING, EVENTS_TRACKER_SUCCESS, logPrefixEventsTracker, logPrefixSyncManager, logPrefixSyncPolling, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixSyncSubmitters, logPrefixImpressionsTracker } from '../constants'; +import { CLIENT_READY_FROM_CACHE, CLIENT_READY, IMPRESSION, IMPRESSION_QUEUEING, NEW_SHARED_CLIENT, NEW_FACTORY, POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP, SYNC_SPLITS_FETCH_RETRY, STREAMING_REFRESH_TOKEN, STREAMING_RECONNECT, STREAMING_CONNECTING, STREAMING_DISABLED, STREAMING_DISCONNECTING, SUBMITTERS_PUSH_FULL_EVENTS_QUEUE, SUBMITTERS_PUSH, SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING, EVENTS_TRACKER_SUCCESS, logPrefixEventsTracker, logPrefixSyncManager, logPrefixSyncPolling, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixSyncSubmitters, logPrefixImpressionsTracker, IMPRESSIONS_TRACKER_SUCCESS } from '../constants'; import { codesWarn } from './warn'; const READY_MSG = 'Split SDK is ready'; @@ -12,8 +12,9 @@ export const codesInfo: [number, string][] = codesWarn.concat([ [IMPRESSION_QUEUEING, logPrefixImpressionsTracker +'Queueing corresponding impression.'], [NEW_SHARED_CLIENT, ' New shared client instance created.'], [NEW_FACTORY, ' New Split SDK instance created.'], - [RETRIEVE_MANAGER, ' Manager instance retrieved.'], [EVENTS_TRACKER_SUCCESS, logPrefixEventsTracker + 'Successfully qeued %s'], + [IMPRESSIONS_TRACKER_SUCCESS, logPrefixImpressionsTracker + 'Successfully stored %s impression(s).'], + // synchronizer [POLLING_SMART_PAUSING, logPrefixSyncPolling + 'Turning segments data polling %s.'], [POLLING_START, logPrefixSyncPolling + 'Starting polling'], diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index 96d36127..b246e0fb 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -1,4 +1,4 @@ -import { ENGINE_VALUE_INVALID, ENGINE_VALUE_NO_ATTRIBUTES, CLIENT_NO_LISTENER, SYNC_MYSEGMENTS_FETCH_RETRY, SYNC_SPLITS_FETCH_FAILS, STREAMING_PARSING_ERROR_FAILS, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_FALLBACK, SUBMITTERS_PUSH_FAILS, SUBMITTERS_PUSH_RETRY, ERROR_EVENTS_TRACKER, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, logPrefixSettings, logPrefixEngineValue, logPrefixEventsTracker, logPrefixSyncMysegments, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixSyncSubmitters } from '../constants'; +import { ENGINE_VALUE_INVALID, ENGINE_VALUE_NO_ATTRIBUTES, CLIENT_NO_LISTENER, SYNC_MYSEGMENTS_FETCH_RETRY, SYNC_SPLITS_FETCH_FAILS, STREAMING_PARSING_ERROR_FAILS, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_FALLBACK, SUBMITTERS_PUSH_FAILS, SUBMITTERS_PUSH_RETRY, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, logPrefixSettings, logPrefixEngineValue, logPrefixSyncMysegments, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixSyncSubmitters } from '../constants'; import { codesError } from './error'; export const codesWarn: [number, string][] = codesError.concat([ @@ -9,12 +9,10 @@ export const codesWarn: [number, string][] = codesError.concat([ [SYNC_MYSEGMENTS_FETCH_RETRY, logPrefixSyncMysegments + 'Retrying download of segments #%s. Reason: %s'], [SYNC_SPLITS_FETCH_FAILS, logPrefixSyncSplits + 'Error while doing fetch of Splits. %s'], [STREAMING_PARSING_ERROR_FAILS, logPrefixSyncStreaming + 'Error parsing SSE error notification: %s'], - [STREAMING_PARSING_MESSAGE_FAILS, logPrefixSyncStreaming + 'Error parsing new SSE message notification: %s'], + [STREAMING_PARSING_MESSAGE_FAILS, logPrefixSyncStreaming + 'Error parsing SSE message notification: %s'], [STREAMING_FALLBACK, logPrefixSyncStreaming + 'Falling back to polling mode. Reason: %s'], [SUBMITTERS_PUSH_FAILS, logPrefixSyncSubmitters + 'Droping %s %s after retry. Reason: %s.'], [SUBMITTERS_PUSH_RETRY, logPrefixSyncSubmitters + 'Failed to push %s %s, keeping data to retry on next iteration. Reason: %s.'], - // SDK - [ERROR_EVENTS_TRACKER, logPrefixEventsTracker + 'Failed to queue %s'], // client status [CLIENT_NOT_READY, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], [CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 0b08ad5a..2fd3e67c 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -10,7 +10,7 @@ import { getMatching } from '../utils/key'; import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; import { createLoggerAPI } from '../logger/sdkLogger'; -import { NEW_FACTORY, RETRIEVE_MANAGER, ERROR_MANAGER_NOT_AVAILABLE } from '../logger/constants'; +import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants'; /** * Modular SDK factory @@ -73,7 +73,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // Sdk client and manager const clientMethod = sdkClientMethodFactory({ eventTracker, impressionsTracker, sdkReadinessManager, settings, storage, syncManager, signalListener }); - const managerInstance = sdkManagerFactory && sdkManagerFactory(log, storage.splits, sdkReadinessManager); + const managerInstance = sdkManagerFactory(log, storage.splits, sdkReadinessManager); syncManager && syncManager.start(); signalListener && signalListener.start(); @@ -87,8 +87,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // Manager API to explore available information // @ts-ignore manager() { - if (managerInstance) log.info(RETRIEVE_MANAGER); - else log.error(ERROR_MANAGER_NOT_AVAILABLE); + log.debug(RETRIEVE_MANAGER); return managerInstance; }, diff --git a/src/sdkFactory/types.ts b/src/sdkFactory/types.ts index 95355d82..dcd6c0d2 100644 --- a/src/sdkFactory/types.ts +++ b/src/sdkFactory/types.ts @@ -46,7 +46,7 @@ export interface ISdkFactoryParams { syncManagerFactory?: (params: ISyncManagerFactoryParams) => ISyncManager, // Sdk manager factory - sdkManagerFactory?: ( + sdkManagerFactory: ( log: ILogger, splits: ISplitsCacheSync | ISplitsCacheAsync, sdkReadinessManager: ISdkReadinessManager diff --git a/src/trackers/eventTracker.ts b/src/trackers/eventTracker.ts index 343e737f..b18c0546 100644 --- a/src/trackers/eventTracker.ts +++ b/src/trackers/eventTracker.ts @@ -36,7 +36,7 @@ export default function eventTrackerFactory( }, 0); } } else { - log.warn(ERROR_EVENTS_TRACKER, [msg]); + log.error(ERROR_EVENTS_TRACKER, [msg]); } return tracked; diff --git a/src/trackers/impressionsTracker.ts b/src/trackers/impressionsTracker.ts index 00e7c25f..5d227892 100644 --- a/src/trackers/impressionsTracker.ts +++ b/src/trackers/impressionsTracker.ts @@ -63,9 +63,9 @@ export default function impressionsTrackerFactory( // If we're on an async storage, handle error and log it. if (thenable(res)) { res.then(() => { - log.debug(IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount, impressionsCount === 1 ? '' : 's']); + log.info(IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount]); }).catch(err => { - log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsCount, impressionsCount === 1 ? '' : 's', err]); + log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsCount, err]); }); } From 3426f1dd561d17f9012632f57c669e42e690006c Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 26 Mar 2021 12:44:31 -0300 Subject: [PATCH 54/58] cleanup imports --- src/logger/messages/debug.ts | 82 ++++++++++++++++++------------------ src/logger/messages/error.ts | 48 ++++++++++----------- src/logger/messages/info.ts | 46 ++++++++++---------- src/logger/messages/warn.ts | 50 +++++++++++----------- 4 files changed, 113 insertions(+), 113 deletions(-) diff --git a/src/logger/messages/debug.ts b/src/logger/messages/debug.ts index 9b4468ae..4f1444bc 100644 --- a/src/logger/messages/debug.ts +++ b/src/logger/messages/debug.ts @@ -1,49 +1,49 @@ -import { ENGINE_COMBINER_AND, ENGINE_COMBINER_IFELSEIF, ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, ENGINE_BUCKET, ENGINE_MATCHER_ALL, ENGINE_MATCHER_BETWEEN, ENGINE_MATCHER_BOOLEAN, ENGINE_MATCHER_CONTAINS_ALL, ENGINE_MATCHER_CONTAINS_ANY, ENGINE_MATCHER_CONTAINS_STRING, ENGINE_MATCHER_DEPENDENCY, ENGINE_MATCHER_DEPENDENCY_PRE, ENGINE_MATCHER_EQUAL, ENGINE_MATCHER_EQUAL_TO_SET, ENGINE_MATCHER_ENDS_WITH, ENGINE_MATCHER_GREATER, ENGINE_MATCHER_LESS, ENGINE_MATCHER_PART_OF, ENGINE_MATCHER_SEGMENT, ENGINE_MATCHER_STRING, ENGINE_MATCHER_STRING_INVALID, ENGINE_MATCHER_STARTS_WITH, ENGINE_MATCHER_WHITELIST, ENGINE_VALUE, ENGINE_SANITIZE, RETRIEVE_CLIENT_DEFAULT, RETRIEVE_CLIENT_EXISTING, RETRIEVE_MANAGER, SYNC_OFFLINE_DATA, SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, STREAMING_NEW_MESSAGE, SYNC_TASK_START, SYNC_TASK_EXECUTE, SYNC_TASK_STOP, SETTINGS_SPLITS_FILTER, logPrefixSettings, logPrefixEngine, logPrefixEngineCombiner, logPrefixEngineMatcher, logPrefixEngineValue, logPrefixSyncOffline, logPrefixSync, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixCleanup, CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../constants'; +import * as c from '../constants'; import { codesInfo } from './info'; export const codesDebug: [number, string][] = codesInfo.concat([ // evaluator - [ENGINE_COMBINER_AND, logPrefixEngineCombiner + '[andCombiner] evaluates to %s'], - [ENGINE_COMBINER_IFELSEIF, logPrefixEngineCombiner + 'Treatment found: %s'], - [ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, logPrefixEngineCombiner + 'All predicates evaluated, no treatment found.'], - [ENGINE_BUCKET, logPrefixEngine + ': using algo "murmur" bucket %s for key %s using seed %s - treatment %s'], - [ENGINE_MATCHER_ALL, logPrefixEngineMatcher + '[allMatcher] is always true'], - [ENGINE_MATCHER_BETWEEN, logPrefixEngineMatcher + '[betweenMatcher] is %s between %s and %s? %s'], - [ENGINE_MATCHER_BOOLEAN, logPrefixEngineMatcher + '[booleanMatcher] %s === %s'], - [ENGINE_MATCHER_CONTAINS_ALL, logPrefixEngineMatcher + '[containsAllMatcher] %s contains all elements of %s? %s'], - [ENGINE_MATCHER_CONTAINS_ANY, logPrefixEngineMatcher + '[containsAnyMatcher] %s contains at least an element of %s? %s'], - [ENGINE_MATCHER_CONTAINS_STRING, logPrefixEngineMatcher + '[containsStringMatcher] %s contains %s? %s'], - [ENGINE_MATCHER_DEPENDENCY, logPrefixEngineMatcher + '[dependencyMatcher] parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], - [ENGINE_MATCHER_DEPENDENCY_PRE, logPrefixEngineMatcher + '[dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], - [ENGINE_MATCHER_EQUAL, logPrefixEngineMatcher + '[equalToMatcher] is %s equal to %s? %s'], - [ENGINE_MATCHER_EQUAL_TO_SET, logPrefixEngineMatcher + '[equalToSetMatcher] is %s equal to set %s? %s'], - [ENGINE_MATCHER_ENDS_WITH, logPrefixEngineMatcher + '[endsWithMatcher] %s ends with %s? %s'], - [ENGINE_MATCHER_GREATER, logPrefixEngineMatcher + '[greaterThanEqualMatcher] is %s greater than %s? %s'], - [ENGINE_MATCHER_LESS, logPrefixEngineMatcher + '[lessThanEqualMatcher] is %s less than %s? %s'], - [ENGINE_MATCHER_PART_OF, logPrefixEngineMatcher + '[partOfMatcher] %s is part of %s? %s'], - [ENGINE_MATCHER_SEGMENT, logPrefixEngineMatcher + '[segmentMatcher] evaluated %s / %s => %s'], - [ENGINE_MATCHER_STRING, logPrefixEngineMatcher + '[stringMatcher] does %s matches with %s? %s'], - [ENGINE_MATCHER_STRING_INVALID, logPrefixEngineMatcher + '[stringMatcher] %s is an invalid regex'], - [ENGINE_MATCHER_STARTS_WITH, logPrefixEngineMatcher + '[startsWithMatcher] %s starts with %s? %s'], - [ENGINE_MATCHER_WHITELIST, logPrefixEngineMatcher + '[whitelistMatcher] evaluated %s in [%s] => %s'], - [ENGINE_VALUE, logPrefixEngineValue + 'Extracted attribute [%s], [%s] will be used for matching.'], - [ENGINE_SANITIZE, logPrefixEngine + ':sanitize: Attempted to sanitize [%s] which should be of type [%s]. Sanitized and processed value => [%s]'], + [c.ENGINE_COMBINER_AND, c.logPrefixEngineCombiner + '[andCombiner] evaluates to %s'], + [c.ENGINE_COMBINER_IFELSEIF, c.logPrefixEngineCombiner + 'Treatment found: %s'], + [c.ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, c.logPrefixEngineCombiner + 'All predicates evaluated, no treatment found.'], + [c.ENGINE_BUCKET, c.logPrefixEngine + ': using algo "murmur" bucket %s for key %s using seed %s - treatment %s'], + [c.ENGINE_MATCHER_ALL, c.logPrefixEngineMatcher + '[allMatcher] is always true'], + [c.ENGINE_MATCHER_BETWEEN, c.logPrefixEngineMatcher + '[betweenMatcher] is %s between %s and %s? %s'], + [c.ENGINE_MATCHER_BOOLEAN, c.logPrefixEngineMatcher + '[booleanMatcher] %s === %s'], + [c.ENGINE_MATCHER_CONTAINS_ALL, c.logPrefixEngineMatcher + '[containsAllMatcher] %s contains all elements of %s? %s'], + [c.ENGINE_MATCHER_CONTAINS_ANY, c.logPrefixEngineMatcher + '[containsAnyMatcher] %s contains at least an element of %s? %s'], + [c.ENGINE_MATCHER_CONTAINS_STRING, c.logPrefixEngineMatcher + '[containsStringMatcher] %s contains %s? %s'], + [c.ENGINE_MATCHER_DEPENDENCY, c.logPrefixEngineMatcher + '[dependencyMatcher] parent split "%s" evaluated to "%s" with label "%s". %s evaluated treatment is part of [%s] ? %s.'], + [c.ENGINE_MATCHER_DEPENDENCY_PRE, c.logPrefixEngineMatcher + '[dependencyMatcher] will evaluate parent split: "%s" with key: %s %s'], + [c.ENGINE_MATCHER_EQUAL, c.logPrefixEngineMatcher + '[equalToMatcher] is %s equal to %s? %s'], + [c.ENGINE_MATCHER_EQUAL_TO_SET, c.logPrefixEngineMatcher + '[equalToSetMatcher] is %s equal to set %s? %s'], + [c.ENGINE_MATCHER_ENDS_WITH, c.logPrefixEngineMatcher + '[endsWithMatcher] %s ends with %s? %s'], + [c.ENGINE_MATCHER_GREATER, c.logPrefixEngineMatcher + '[greaterThanEqualMatcher] is %s greater than %s? %s'], + [c.ENGINE_MATCHER_LESS, c.logPrefixEngineMatcher + '[lessThanEqualMatcher] is %s less than %s? %s'], + [c.ENGINE_MATCHER_PART_OF, c.logPrefixEngineMatcher + '[partOfMatcher] %s is part of %s? %s'], + [c.ENGINE_MATCHER_SEGMENT, c.logPrefixEngineMatcher + '[segmentMatcher] evaluated %s / %s => %s'], + [c.ENGINE_MATCHER_STRING, c.logPrefixEngineMatcher + '[stringMatcher] does %s matches with %s? %s'], + [c.ENGINE_MATCHER_STRING_INVALID, c.logPrefixEngineMatcher + '[stringMatcher] %s is an invalid regex'], + [c.ENGINE_MATCHER_STARTS_WITH, c.logPrefixEngineMatcher + '[startsWithMatcher] %s starts with %s? %s'], + [c.ENGINE_MATCHER_WHITELIST, c.logPrefixEngineMatcher + '[whitelistMatcher] evaluated %s in [%s] => %s'], + [c.ENGINE_VALUE, c.logPrefixEngineValue + 'Extracted attribute [%s], [%s] will be used for matching.'], + [c.ENGINE_SANITIZE, c.logPrefixEngine + ':sanitize: Attempted to sanitize [%s] which should be of type [%s]. Sanitized and processed value => [%s]'], // SDK - [CLEANUP_REGISTERING, logPrefixCleanup + 'Registering cleanup handler %s'], - [CLEANUP_DEREGISTERING, logPrefixCleanup + 'Deregistering cleanup handler %s'], - [RETRIEVE_CLIENT_DEFAULT, ' Retrieving default SDK client.'], - [RETRIEVE_CLIENT_EXISTING, ' Retrieving existing SDK client.'], - [RETRIEVE_MANAGER, ' Retrieving manager instance.'], + [c.CLEANUP_REGISTERING, c.logPrefixCleanup + 'Registering cleanup handler %s'], + [c.CLEANUP_DEREGISTERING, c.logPrefixCleanup + 'Deregistering cleanup handler %s'], + [c.RETRIEVE_CLIENT_DEFAULT, ' Retrieving default SDK client.'], + [c.RETRIEVE_CLIENT_EXISTING, ' Retrieving existing SDK client.'], + [c.RETRIEVE_MANAGER, ' Retrieving manager instance.'], // synchronizer - [SYNC_OFFLINE_DATA, logPrefixSyncOffline + 'Splits data: \n%s'], - [SYNC_SPLITS_FETCH, logPrefixSyncSplits + 'Spin up split update using since = %s'], - [SYNC_SPLITS_NEW, logPrefixSyncSplits + 'New splits %s'], - [SYNC_SPLITS_REMOVED, logPrefixSyncSplits + 'Removed splits %s'], - [SYNC_SPLITS_SEGMENTS, logPrefixSyncSplits + 'Segment names collected %s'], - [STREAMING_NEW_MESSAGE, logPrefixSyncStreaming + 'New SSE message received, with data: %s.'], - [SYNC_TASK_START, logPrefixSync + ': Starting %s. Running each %s millis'], - [SYNC_TASK_EXECUTE, logPrefixSync + ': Running %s'], - [SYNC_TASK_STOP, logPrefixSync + ': Stopping %s'], + [c.SYNC_OFFLINE_DATA, c.logPrefixSyncOffline + 'Splits data: \n%s'], + [c.SYNC_SPLITS_FETCH, c.logPrefixSyncSplits + 'Spin up split update using since = %s'], + [c.SYNC_SPLITS_NEW, c.logPrefixSyncSplits + 'New splits %s'], + [c.SYNC_SPLITS_REMOVED, c.logPrefixSyncSplits + 'Removed splits %s'], + [c.SYNC_SPLITS_SEGMENTS, c.logPrefixSyncSplits + 'Segment names collected %s'], + [c.STREAMING_NEW_MESSAGE, c.logPrefixSyncStreaming + 'New SSE message received, with data: %s.'], + [c.SYNC_TASK_START, c.logPrefixSync + ': Starting %s. Running each %s millis'], + [c.SYNC_TASK_EXECUTE, c.logPrefixSync + ': Running %s'], + [c.SYNC_TASK_STOP, c.logPrefixSync + ': Stopping %s'], // initialization / settings validation - [SETTINGS_SPLITS_FILTER, logPrefixSettings + ': splits filtering criteria is "%s".'] + [c.SETTINGS_SPLITS_FILTER, c.logPrefixSettings + ': splits filtering criteria is "%s".'] ]); diff --git a/src/logger/messages/error.ts b/src/logger/messages/error.ts index 2e4eb9c7..0eea8c02 100644 --- a/src/logger/messages/error.ts +++ b/src/logger/messages/error.ts @@ -1,33 +1,33 @@ -import { ERROR_ENGINE_COMBINER_IFELSEIF, ERROR_LOGLEVEL_INVALID, ERROR_CLIENT_LISTENER, ERROR_CLIENT_CANNOT_GET_READY, ERROR_SYNC_OFFLINE_LOADING, ERROR_STREAMING_SSE, ERROR_STREAMING_AUTH, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER, ERROR_EVENT_TYPE_FORMAT, ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, ERROR_NOT_FINITE, ERROR_CLIENT_DESTROYED, ERROR_NULL, ERROR_TOO_LONG, ERROR_INVALID_KEY_OBJECT, ERROR_INVALID, ERROR_EMPTY, ERROR_EMPTY_ARRAY, ERROR_INVALID_IMPRESSIONS_MODE, ERROR_HTTP, logPrefixSettings, logPrefixEngineCombiner, logPrefixSyncOffline, logPrefixSyncStreaming, logPrefixImpressionsTracker, ERROR_EVENTS_TRACKER, logPrefixEventsTracker } from '../constants'; +import * as c from '../constants'; export const codesError: [number, string][] = [ // evaluator - [ERROR_ENGINE_COMBINER_IFELSEIF, logPrefixEngineCombiner + 'Invalid Split, no valid rules found'], + [c.ERROR_ENGINE_COMBINER_IFELSEIF, c.logPrefixEngineCombiner + 'Invalid Split, no valid rules found'], // SDK - [ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'], - [ERROR_CLIENT_CANNOT_GET_READY, ' The SDK will not get ready. Reason: %s'], - [ERROR_IMPRESSIONS_TRACKER, logPrefixImpressionsTracker + 'Could not store impressions bulk with %s impression(s). Error: %s'], - [ERROR_IMPRESSIONS_LISTENER, logPrefixImpressionsTracker + 'Impression listener logImpression method threw: %s.'], - [ERROR_EVENTS_TRACKER, logPrefixEventsTracker + 'Failed to queue %s'], + [c.ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'], + [c.ERROR_CLIENT_CANNOT_GET_READY, ' The SDK will not get ready. Reason: %s'], + [c.ERROR_IMPRESSIONS_TRACKER, c.logPrefixImpressionsTracker + 'Could not store impressions bulk with %s impression(s). Error: %s'], + [c.ERROR_IMPRESSIONS_LISTENER, c.logPrefixImpressionsTracker + 'Impression listener logImpression method threw: %s.'], + [c.ERROR_EVENTS_TRACKER, c.logPrefixEventsTracker + 'Failed to queue %s'], // synchronizer - [ERROR_SYNC_OFFLINE_LOADING, logPrefixSyncOffline + 'There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], - [ERROR_STREAMING_SSE, logPrefixSyncStreaming + 'Fail to connect to streaming, with error message: %s'], - [ERROR_STREAMING_AUTH, logPrefixSyncStreaming + 'Failed to authenticate for streaming. Error: "%s".'], - [ERROR_HTTP, ' Response status is not OK. Status: %s. URL: %s. Message: %s'], + [c.ERROR_SYNC_OFFLINE_LOADING, c.logPrefixSyncOffline + 'There was an issue loading the mock Splits data, no changes will be applied to the current cache. %s'], + [c.ERROR_STREAMING_SSE, c.logPrefixSyncStreaming + 'Fail to connect to streaming, with error message: %s'], + [c.ERROR_STREAMING_AUTH, c.logPrefixSyncStreaming + 'Failed to authenticate for streaming. Error: "%s".'], + [c.ERROR_HTTP, ' Response status is not OK. Status: %s. URL: %s. Message: %s'], // client status - [ERROR_CLIENT_LISTENER, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], - [ERROR_CLIENT_DESTROYED, '%s: Client has already been destroyed - no calls possible.'], + [c.ERROR_CLIENT_LISTENER, 'A listener was added for %s on the SDK, which has already fired and won\'t be emitted again. The callback won\'t be executed.'], + [c.ERROR_CLIENT_DESTROYED, '%s: Client has already been destroyed - no calls possible.'], // input validation - [ERROR_EVENT_TYPE_FORMAT, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], - [ERROR_NOT_PLAIN_OBJECT, '%s: %s must be a plain object.'], - [ERROR_SIZE_EXCEEDED, '%s: the maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'], - [ERROR_NOT_FINITE, '%s: value must be a finite number.'], - [ERROR_NULL, '%s: you passed a null or undefined %s. It must be a non-empty string.'], - [ERROR_TOO_LONG, '%s: %s too long. It must have 250 characters or less.'], - [ERROR_INVALID_KEY_OBJECT, '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'], - [ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'], - [ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'], - [ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'], + [c.ERROR_EVENT_TYPE_FORMAT, '%s: you passed "%s", event_type must adhere to the regular expression /^[a-zA-Z0-9][-_.:a-zA-Z0-9]{0,79}$/g. This means an event_type must be alphanumeric, cannot be more than 80 characters long, and can only include a dash, underscore, period, or colon as separators of alphanumeric characters.'], + [c.ERROR_NOT_PLAIN_OBJECT, '%s: %s must be a plain object.'], + [c.ERROR_SIZE_EXCEEDED, '%s: the maximum size allowed for the properties is 32768 bytes, which was exceeded. Event not queued.'], + [c.ERROR_NOT_FINITE, '%s: value must be a finite number.'], + [c.ERROR_NULL, '%s: you passed a null or undefined %s. It must be a non-empty string.'], + [c.ERROR_TOO_LONG, '%s: %s too long. It must have 250 characters or less.'], + [c.ERROR_INVALID_KEY_OBJECT, '%s: Key must be an object with bucketingKey and matchingKey with valid string properties.'], + [c.ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'], + [c.ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'], + [c.ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'], // initialization / settings validation - [ERROR_INVALID_IMPRESSIONS_MODE, logPrefixSettings + ': you passed an invalid "impressionsMode". It should be one of the following values: %s. Defaulting to "%s" mode.'], + [c.ERROR_INVALID_IMPRESSIONS_MODE, c.logPrefixSettings + ': you passed an invalid "impressionsMode". It should be one of the following values: %s. Defaulting to "%s" mode.'], ]; diff --git a/src/logger/messages/info.ts b/src/logger/messages/info.ts index 6c00a5ff..2877a9d8 100644 --- a/src/logger/messages/info.ts +++ b/src/logger/messages/info.ts @@ -1,33 +1,33 @@ -import { CLIENT_READY_FROM_CACHE, CLIENT_READY, IMPRESSION, IMPRESSION_QUEUEING, NEW_SHARED_CLIENT, NEW_FACTORY, POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP, SYNC_SPLITS_FETCH_RETRY, STREAMING_REFRESH_TOKEN, STREAMING_RECONNECT, STREAMING_CONNECTING, STREAMING_DISABLED, STREAMING_DISCONNECTING, SUBMITTERS_PUSH_FULL_EVENTS_QUEUE, SUBMITTERS_PUSH, SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING, EVENTS_TRACKER_SUCCESS, logPrefixEventsTracker, logPrefixSyncManager, logPrefixSyncPolling, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixSyncSubmitters, logPrefixImpressionsTracker, IMPRESSIONS_TRACKER_SUCCESS } from '../constants'; +import * as c from '../constants'; import { codesWarn } from './warn'; const READY_MSG = 'Split SDK is ready'; export const codesInfo: [number, string][] = codesWarn.concat([ // client status - [CLIENT_READY_FROM_CACHE, READY_MSG + ' from cache'], - [CLIENT_READY, READY_MSG], + [c.CLIENT_READY_FROM_CACHE, READY_MSG + ' from cache'], + [c.CLIENT_READY, READY_MSG], // SDK - [IMPRESSION, logPrefixImpressionsTracker +'Split: %s. Key: %s. Evaluation: %s. Label: %s'], - [IMPRESSION_QUEUEING, logPrefixImpressionsTracker +'Queueing corresponding impression.'], - [NEW_SHARED_CLIENT, ' New shared client instance created.'], - [NEW_FACTORY, ' New Split SDK instance created.'], - [EVENTS_TRACKER_SUCCESS, logPrefixEventsTracker + 'Successfully qeued %s'], - [IMPRESSIONS_TRACKER_SUCCESS, logPrefixImpressionsTracker + 'Successfully stored %s impression(s).'], + [c.IMPRESSION, c.logPrefixImpressionsTracker +'Split: %s. Key: %s. Evaluation: %s. Label: %s'], + [c.IMPRESSION_QUEUEING, c.logPrefixImpressionsTracker +'Queueing corresponding impression.'], + [c.NEW_SHARED_CLIENT, ' New shared client instance created.'], + [c.NEW_FACTORY, ' New Split SDK instance created.'], + [c.EVENTS_TRACKER_SUCCESS, c.logPrefixEventsTracker + 'Successfully qeued %s'], + [c.IMPRESSIONS_TRACKER_SUCCESS, c.logPrefixImpressionsTracker + 'Successfully stored %s impression(s).'], // synchronizer - [POLLING_SMART_PAUSING, logPrefixSyncPolling + 'Turning segments data polling %s.'], - [POLLING_START, logPrefixSyncPolling + 'Starting polling'], - [POLLING_STOP, logPrefixSyncPolling + 'Stopping polling'], - [SYNC_SPLITS_FETCH_RETRY, logPrefixSyncSplits + 'Retrying download of splits #%s. Reason: %s'], - [SUBMITTERS_PUSH_FULL_EVENTS_QUEUE, logPrefixSyncSubmitters + 'Flushing full events queue and reseting timer.'], - [SUBMITTERS_PUSH, logPrefixSyncSubmitters + 'Pushing %s %s.'], - [STREAMING_REFRESH_TOKEN, logPrefixSyncStreaming + 'Refreshing streaming token in %s seconds.'], - [STREAMING_RECONNECT, logPrefixSyncStreaming + 'Attempting to reconnect in %s seconds.'], - [STREAMING_CONNECTING, logPrefixSyncStreaming + 'Connecting to streaming.'], - [STREAMING_DISABLED, logPrefixSyncStreaming + 'Streaming is disabled for given Api key. Switching to polling mode.'], - [STREAMING_DISCONNECTING, logPrefixSyncStreaming + 'Disconnecting from streaming.'], - [SYNC_START_POLLING, logPrefixSyncManager + 'Streaming not available. Starting polling.'], - [SYNC_CONTINUE_POLLING, logPrefixSyncManager + 'Streaming couldn\'t connect. Continue polling.'], - [SYNC_STOP_POLLING, logPrefixSyncManager + 'Streaming (re)connected. Syncing and stopping polling.'], + [c.POLLING_SMART_PAUSING, c.logPrefixSyncPolling + 'Turning segments data polling %s.'], + [c.POLLING_START, c.logPrefixSyncPolling + 'Starting polling'], + [c.POLLING_STOP, c.logPrefixSyncPolling + 'Stopping polling'], + [c.SYNC_SPLITS_FETCH_RETRY, c.logPrefixSyncSplits + 'Retrying download of splits #%s. Reason: %s'], + [c.SUBMITTERS_PUSH_FULL_EVENTS_QUEUE, c.logPrefixSyncSubmitters + 'Flushing full events queue and reseting timer.'], + [c.SUBMITTERS_PUSH, c.logPrefixSyncSubmitters + 'Pushing %s %s.'], + [c.STREAMING_REFRESH_TOKEN, c.logPrefixSyncStreaming + 'Refreshing streaming token in %s seconds.'], + [c.STREAMING_RECONNECT, c.logPrefixSyncStreaming + 'Attempting to reconnect in %s seconds.'], + [c.STREAMING_CONNECTING, c.logPrefixSyncStreaming + 'Connecting to streaming.'], + [c.STREAMING_DISABLED, c.logPrefixSyncStreaming + 'Streaming is disabled for given Api key. Switching to polling mode.'], + [c.STREAMING_DISCONNECTING, c.logPrefixSyncStreaming + 'Disconnecting from streaming.'], + [c.SYNC_START_POLLING, c.logPrefixSyncManager + 'Streaming not available. Starting polling.'], + [c.SYNC_CONTINUE_POLLING, c.logPrefixSyncManager + 'Streaming couldn\'t connect. Continue polling.'], + [c.SYNC_STOP_POLLING, c.logPrefixSyncManager + 'Streaming (re)connected. Syncing and stopping polling.'], ]); diff --git a/src/logger/messages/warn.ts b/src/logger/messages/warn.ts index b246e0fb..e10da2f5 100644 --- a/src/logger/messages/warn.ts +++ b/src/logger/messages/warn.ts @@ -1,34 +1,34 @@ -import { ENGINE_VALUE_INVALID, ENGINE_VALUE_NO_ATTRIBUTES, CLIENT_NO_LISTENER, SYNC_MYSEGMENTS_FETCH_RETRY, SYNC_SPLITS_FETCH_FAILS, STREAMING_PARSING_ERROR_FAILS, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_FALLBACK, SUBMITTERS_PUSH_FAILS, SUBMITTERS_PUSH_RETRY, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES, CLIENT_NOT_READY, WARN_CONVERTING, WARN_TRIMMING, WARN_NOT_EXISTENT_SPLIT, WARN_LOWERCASE_TRAFFIC_TYPE, WARN_NOT_EXISTENT_TT, WARN_INTEGRATION_INVALID, WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_INVALID, WARN_SPLITS_FILTER_EMPTY, WARN_STORAGE_INVALID, WARN_API_KEY, logPrefixSettings, logPrefixEngineValue, logPrefixSyncMysegments, logPrefixSyncSplits, logPrefixSyncStreaming, logPrefixSyncSubmitters } from '../constants'; +import * as c from '../constants'; import { codesError } from './error'; export const codesWarn: [number, string][] = codesError.concat([ // evaluator - [ENGINE_VALUE_INVALID, logPrefixEngineValue + 'Value %s doesn\'t match with expected type.'], - [ENGINE_VALUE_NO_ATTRIBUTES, logPrefixEngineValue + 'Defined attribute [%s], no attributes received.'], + [c.ENGINE_VALUE_INVALID, c.logPrefixEngineValue + 'Value %s doesn\'t match with expected type.'], + [c.ENGINE_VALUE_NO_ATTRIBUTES, c.logPrefixEngineValue + 'Defined attribute [%s], no attributes received.'], // synchronizer - [SYNC_MYSEGMENTS_FETCH_RETRY, logPrefixSyncMysegments + 'Retrying download of segments #%s. Reason: %s'], - [SYNC_SPLITS_FETCH_FAILS, logPrefixSyncSplits + 'Error while doing fetch of Splits. %s'], - [STREAMING_PARSING_ERROR_FAILS, logPrefixSyncStreaming + 'Error parsing SSE error notification: %s'], - [STREAMING_PARSING_MESSAGE_FAILS, logPrefixSyncStreaming + 'Error parsing SSE message notification: %s'], - [STREAMING_FALLBACK, logPrefixSyncStreaming + 'Falling back to polling mode. Reason: %s'], - [SUBMITTERS_PUSH_FAILS, logPrefixSyncSubmitters + 'Droping %s %s after retry. Reason: %s.'], - [SUBMITTERS_PUSH_RETRY, logPrefixSyncSubmitters + 'Failed to push %s %s, keeping data to retry on next iteration. Reason: %s.'], + [c.SYNC_MYSEGMENTS_FETCH_RETRY, c.logPrefixSyncMysegments + 'Retrying download of segments #%s. Reason: %s'], + [c.SYNC_SPLITS_FETCH_FAILS, c.logPrefixSyncSplits + 'Error while doing fetch of Splits. %s'], + [c.STREAMING_PARSING_ERROR_FAILS, c.logPrefixSyncStreaming + 'Error parsing SSE error notification: %s'], + [c.STREAMING_PARSING_MESSAGE_FAILS, c.logPrefixSyncStreaming + 'Error parsing SSE message notification: %s'], + [c.STREAMING_FALLBACK, c.logPrefixSyncStreaming + 'Falling back to polling mode. Reason: %s'], + [c.SUBMITTERS_PUSH_FAILS, c.logPrefixSyncSubmitters + 'Droping %s %s after retry. Reason: %s.'], + [c.SUBMITTERS_PUSH_RETRY, c.logPrefixSyncSubmitters + 'Failed to push %s %s, keeping data to retry on next iteration. Reason: %s.'], // client status - [CLIENT_NOT_READY, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], - [CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], + [c.CLIENT_NOT_READY, '%s: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method.'], + [c.CLIENT_NO_LISTENER, 'No listeners for SDK Readiness detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet ready.'], // input validation - [WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'], - [WARN_TRIMMING_PROPERTIES, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], - [WARN_CONVERTING, '%s: %s "%s" is not of type string, converting.'], - [WARN_TRIMMING, '%s: %s "%s" has extra whitespace, trimming.'], - [WARN_NOT_EXISTENT_SPLIT, '%s: split "%s" does not exist in this environment, please double check what splits exist in the web console.'], - [WARN_LOWERCASE_TRAFFIC_TYPE, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], - [WARN_NOT_EXISTENT_TT, '%s: traffic type "%s" does not have any corresponding split in this environment, make sure you\'re tracking your events to a valid traffic type defined in the web console.'], + [c.WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'], + [c.WARN_TRIMMING_PROPERTIES, '%s: Event has more than 300 properties. Some of them will be trimmed when processed.'], + [c.WARN_CONVERTING, '%s: %s "%s" is not of type string, converting.'], + [c.WARN_TRIMMING, '%s: %s "%s" has extra whitespace, trimming.'], + [c.WARN_NOT_EXISTENT_SPLIT, '%s: split "%s" does not exist in this environment, please double check what splits exist in the web console.'], + [c.WARN_LOWERCASE_TRAFFIC_TYPE, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'], + [c.WARN_NOT_EXISTENT_TT, '%s: traffic type "%s" does not have any corresponding split in this environment, make sure you\'re tracking your events to a valid traffic type defined in the web console.'], // initialization / settings validation - [WARN_INTEGRATION_INVALID, logPrefixSettings+': %s integration %s at settings %s invalid. %s'], - [WARN_SPLITS_FILTER_IGNORED, logPrefixSettings+': split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'], - [WARN_SPLITS_FILTER_INVALID, logPrefixSettings+': split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'], - [WARN_SPLITS_FILTER_EMPTY, logPrefixSettings+': splitFilters configuration must be a non-empty array of filter objects.'], - [WARN_STORAGE_INVALID, logPrefixSettings+': The provided storage is invalid. Fallbacking into default MEMORY storage'], - [WARN_API_KEY, logPrefixSettings+': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'] + [c.WARN_INTEGRATION_INVALID, c.logPrefixSettings+': %s integration %s at settings %s invalid. %s'], + [c.WARN_SPLITS_FILTER_IGNORED, c.logPrefixSettings+': split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'], + [c.WARN_SPLITS_FILTER_INVALID, c.logPrefixSettings+': split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'], + [c.WARN_SPLITS_FILTER_EMPTY, c.logPrefixSettings+': splitFilters configuration must be a non-empty array of filter objects.'], + [c.WARN_STORAGE_INVALID, c.logPrefixSettings+': The provided storage is invalid. Fallbacking into default MEMORY storage'], + [c.WARN_API_KEY, c.logPrefixSettings+': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'] ]); From 4811f19c86f620ef83e6e838401f79c63363f077 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 26 Mar 2021 15:29:51 -0300 Subject: [PATCH 55/58] ordered constant values --- src/logger/constants.ts | 148 ++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/src/logger/constants.ts b/src/logger/constants.ts index 75e18f7e..46cac217 100644 --- a/src/logger/constants.ts +++ b/src/logger/constants.ts @@ -23,28 +23,28 @@ export const ENGINE_MATCHER_ENDS_WITH = 14; export const ENGINE_MATCHER_GREATER = 15; export const ENGINE_MATCHER_LESS = 16; export const ENGINE_MATCHER_PART_OF = 17; -export const ENGINE_MATCHER_SEGMENT = 19; -export const ENGINE_MATCHER_STRING = 20; -export const ENGINE_MATCHER_STRING_INVALID = 21; -export const ENGINE_MATCHER_STARTS_WITH = 22; -export const ENGINE_MATCHER_WHITELIST = 23; -export const ENGINE_VALUE = 24; -export const ENGINE_SANITIZE = 25; -export const CLEANUP_REGISTERING = 26; -export const CLEANUP_DEREGISTERING = 27; -export const RETRIEVE_CLIENT_DEFAULT = 32; -export const RETRIEVE_CLIENT_EXISTING = 33; -export const RETRIEVE_MANAGER = 34; -export const SYNC_OFFLINE_DATA = 36; -export const SYNC_SPLITS_FETCH = 42; -export const SYNC_SPLITS_NEW = 43; -export const SYNC_SPLITS_REMOVED = 44; -export const SYNC_SPLITS_SEGMENTS = 45; -export const STREAMING_NEW_MESSAGE = 46; -export const SYNC_TASK_START = 47; -export const SYNC_TASK_EXECUTE = 48; -export const SYNC_TASK_STOP = 49; -export const SETTINGS_SPLITS_FILTER = 51; +export const ENGINE_MATCHER_SEGMENT = 18; +export const ENGINE_MATCHER_STRING = 19; +export const ENGINE_MATCHER_STRING_INVALID = 20; +export const ENGINE_MATCHER_STARTS_WITH = 21; +export const ENGINE_MATCHER_WHITELIST = 22; +export const ENGINE_VALUE = 23; +export const ENGINE_SANITIZE = 24; +export const CLEANUP_REGISTERING = 25; +export const CLEANUP_DEREGISTERING = 26; +export const RETRIEVE_CLIENT_DEFAULT = 27; +export const RETRIEVE_CLIENT_EXISTING = 28; +export const RETRIEVE_MANAGER = 29; +export const SYNC_OFFLINE_DATA = 30; +export const SYNC_SPLITS_FETCH = 31; +export const SYNC_SPLITS_NEW = 32; +export const SYNC_SPLITS_REMOVED = 33; +export const SYNC_SPLITS_SEGMENTS = 34; +export const STREAMING_NEW_MESSAGE = 35; +export const SYNC_TASK_START = 36; +export const SYNC_TASK_EXECUTE = 37; +export const SYNC_TASK_STOP = 38; +export const SETTINGS_SPLITS_FILTER = 39; export const CLIENT_READY_FROM_CACHE = 100; export const CLIENT_READY = 101; @@ -52,27 +52,27 @@ export const IMPRESSION = 102; export const IMPRESSION_QUEUEING = 103; export const NEW_SHARED_CLIENT = 104; export const NEW_FACTORY = 105; -export const POLLING_SMART_PAUSING = 107; -export const POLLING_START = 108; -export const POLLING_STOP = 109; -export const SYNC_SPLITS_FETCH_RETRY = 110; -export const STREAMING_REFRESH_TOKEN = 111; -export const STREAMING_RECONNECT = 112; -export const STREAMING_CONNECTING = 113; -export const STREAMING_DISABLED = 114; -export const STREAMING_DISCONNECTING = 115; -export const SUBMITTERS_PUSH_FULL_EVENTS_QUEUE = 116; -export const SUBMITTERS_PUSH = 117; -export const SYNC_START_POLLING = 118; -export const SYNC_CONTINUE_POLLING = 119; -export const SYNC_STOP_POLLING = 120; -export const EVENTS_TRACKER_SUCCESS = 121; -export const IMPRESSIONS_TRACKER_SUCCESS = 122; +export const POLLING_SMART_PAUSING = 106; +export const POLLING_START = 107; +export const POLLING_STOP = 108; +export const SYNC_SPLITS_FETCH_RETRY = 109; +export const STREAMING_REFRESH_TOKEN = 110; +export const STREAMING_RECONNECT = 111; +export const STREAMING_CONNECTING = 112; +export const STREAMING_DISABLED = 113; +export const STREAMING_DISCONNECTING = 114; +export const SUBMITTERS_PUSH_FULL_EVENTS_QUEUE = 115; +export const SUBMITTERS_PUSH = 116; +export const SYNC_START_POLLING = 117; +export const SYNC_CONTINUE_POLLING = 118; +export const SYNC_STOP_POLLING = 119; +export const EVENTS_TRACKER_SUCCESS = 120; +export const IMPRESSIONS_TRACKER_SUCCESS = 121; export const ENGINE_VALUE_INVALID = 200; export const ENGINE_VALUE_NO_ATTRIBUTES = 201; export const CLIENT_NO_LISTENER = 202; -export const CLIENT_NOT_READY = 214; +export const CLIENT_NOT_READY = 203; export const SYNC_MYSEGMENTS_FETCH_RETRY = 204; export const SYNC_SPLITS_FETCH_FAILS = 205; export const STREAMING_PARSING_ERROR_FAILS = 206; @@ -80,43 +80,43 @@ export const STREAMING_PARSING_MESSAGE_FAILS = 207; export const STREAMING_FALLBACK = 208; export const SUBMITTERS_PUSH_FAILS = 209; export const SUBMITTERS_PUSH_RETRY = 210; -export const WARN_SETTING_NULL = 212; -export const WARN_TRIMMING_PROPERTIES = 213; -export const WARN_CONVERTING = 215; -export const WARN_TRIMMING = 217; -export const WARN_NOT_EXISTENT_SPLIT = 218; -export const WARN_LOWERCASE_TRAFFIC_TYPE = 219; -export const WARN_NOT_EXISTENT_TT = 220; -export const WARN_INTEGRATION_INVALID = 221; -export const WARN_SPLITS_FILTER_IGNORED = 222; -export const WARN_SPLITS_FILTER_INVALID = 223; -export const WARN_SPLITS_FILTER_EMPTY = 224; -export const WARN_STORAGE_INVALID = 225; -export const WARN_API_KEY = 226; +export const WARN_SETTING_NULL = 211; +export const WARN_TRIMMING_PROPERTIES = 212; +export const WARN_CONVERTING = 213; +export const WARN_TRIMMING = 214; +export const WARN_NOT_EXISTENT_SPLIT = 215; +export const WARN_LOWERCASE_TRAFFIC_TYPE = 216; +export const WARN_NOT_EXISTENT_TT = 217; +export const WARN_INTEGRATION_INVALID = 218; +export const WARN_SPLITS_FILTER_IGNORED = 219; +export const WARN_SPLITS_FILTER_INVALID = 220; +export const WARN_SPLITS_FILTER_EMPTY = 221; +export const WARN_STORAGE_INVALID = 222; +export const WARN_API_KEY = 223; export const ERROR_ENGINE_COMBINER_IFELSEIF = 300; -export const ERROR_LOGLEVEL_INVALID = 302; -export const ERROR_CLIENT_LISTENER = 303; -export const ERROR_CLIENT_CANNOT_GET_READY = 305; -export const ERROR_SYNC_OFFLINE_LOADING = 307; -export const ERROR_STREAMING_SSE = 309; -export const ERROR_STREAMING_AUTH = 310; -export const ERROR_IMPRESSIONS_TRACKER = 311; -export const ERROR_IMPRESSIONS_LISTENER = 312; -export const ERROR_EVENTS_TRACKER = 313; -export const ERROR_EVENT_TYPE_FORMAT = 314; -export const ERROR_NOT_PLAIN_OBJECT = 318; -export const ERROR_SIZE_EXCEEDED = 319; -export const ERROR_NOT_FINITE = 320; -export const ERROR_CLIENT_DESTROYED = 321; -export const ERROR_NULL = 322; -export const ERROR_TOO_LONG = 323; -export const ERROR_INVALID_KEY_OBJECT = 326; -export const ERROR_INVALID = 332; -export const ERROR_EMPTY = 333; -export const ERROR_EMPTY_ARRAY = 334; -export const ERROR_INVALID_IMPRESSIONS_MODE = 338; -export const ERROR_HTTP = 339; +export const ERROR_LOGLEVEL_INVALID = 301; +export const ERROR_CLIENT_LISTENER = 302; +export const ERROR_CLIENT_CANNOT_GET_READY = 303; +export const ERROR_SYNC_OFFLINE_LOADING = 304; +export const ERROR_STREAMING_SSE = 305; +export const ERROR_STREAMING_AUTH = 306; +export const ERROR_IMPRESSIONS_TRACKER = 307; +export const ERROR_IMPRESSIONS_LISTENER = 308; +export const ERROR_EVENTS_TRACKER = 309; +export const ERROR_EVENT_TYPE_FORMAT = 310; +export const ERROR_NOT_PLAIN_OBJECT = 311; +export const ERROR_SIZE_EXCEEDED = 312; +export const ERROR_NOT_FINITE = 313; +export const ERROR_CLIENT_DESTROYED = 314; +export const ERROR_NULL = 315; +export const ERROR_TOO_LONG = 316; +export const ERROR_INVALID_KEY_OBJECT = 317; +export const ERROR_INVALID = 318; +export const ERROR_EMPTY = 319; +export const ERROR_EMPTY_ARRAY = 320; +export const ERROR_INVALID_IMPRESSIONS_MODE = 321; +export const ERROR_HTTP = 322; // Log prefixes (a.k.a. tags or categories) export const logPrefixSettings = 'settings'; From 55d299d5fdf51b139afc88f4c59bd6e290394742 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 26 Mar 2021 15:56:37 -0300 Subject: [PATCH 56/58] polishing on UTs --- src/integrations/__tests__/browser.spec.ts | 8 ++-- .../ga/__tests__/GaToSplit.spec.ts | 2 +- .../ga/__tests__/SplitToGa.spec.ts | 14 +++---- src/listeners/__tests__/browser.spec.ts | 26 ++++++------ src/listeners/__tests__/node.spec.ts | 42 +++++++++---------- .../__tests__/sdkReadinessManager.spec.ts | 32 +++++++------- .../__tests__/sdkClientMethod.spec.ts | 4 +- .../__tests__/ImpressionsCacheInRedis.spec.ts | 4 +- .../inRedis/__tests__/RedisAdapter.spec.ts | 2 +- .../__tests__/splitChangesUpdater.spec.ts | 6 +-- .../SSEClient/__tests__/index.spec.ts | 10 ++--- src/trackers/__tests__/eventTracker.spec.ts | 6 +-- .../__tests__/impressionsTracker.spec.ts | 20 ++++----- .../__tests__/attributes.spec.ts | 10 ++--- .../inputValidation/__tests__/split.spec.ts | 6 +-- .../__tests__/splitExistance.spec.ts | 12 +++--- .../inputValidation/__tests__/splits.spec.ts | 20 ++++----- .../__tests__/trafficType.spec.ts | 12 +++--- src/utils/lang/__tests__/index.spec.ts | 6 +-- 19 files changed, 121 insertions(+), 121 deletions(-) diff --git a/src/integrations/__tests__/browser.spec.ts b/src/integrations/__tests__/browser.spec.ts index e4237f91..9bab3e99 100644 --- a/src/integrations/__tests__/browser.spec.ts +++ b/src/integrations/__tests__/browser.spec.ts @@ -47,8 +47,8 @@ describe('IntegrationsManagerFactory for browser', () => { let integrations: BrowserIntegration[] = [{ type: GOOGLE_ANALYTICS_TO_SPLIT }, { type: SPLIT_TO_GOOGLE_ANALYTICS }]; const instance2 = browserIMF(integrations, fakeParams as any) as IIntegrationManager; - expect((GaToSplitMock as jest.Mock).mock.calls.length).toBe(1); // GaToSplit invoked once - expect((SplitToGaMock as unknown as jest.Mock).mock.calls.length).toBe(1); // SplitToGa invoked once + expect(GaToSplitMock).toBeCalledTimes(1); // GaToSplit invoked once + expect(SplitToGaMock).toBeCalledTimes(1); // SplitToGa invoked once expect(typeof instance2.handleImpression).toBe('function'); // The instance should implement the handleImpression method if settings.integrations has items that register a listener. expect(typeof instance2.handleEvent).toBe('function'); // The instance should implement the handleEvent method if settings.integrations has items that register a listener. @@ -56,8 +56,8 @@ describe('IntegrationsManagerFactory for browser', () => { integrations = [{ type: GOOGLE_ANALYTICS_TO_SPLIT }, { type: SPLIT_TO_GOOGLE_ANALYTICS }, { type: GOOGLE_ANALYTICS_TO_SPLIT }, { type: SPLIT_TO_GOOGLE_ANALYTICS }, { type: SPLIT_TO_GOOGLE_ANALYTICS }]; browserIMF(integrations, fakeParams as any); - expect((GaToSplitMock as jest.Mock).mock.calls.length).toBe(2); // GaToSplit invoked twice - expect((SplitToGaMock as unknown as jest.Mock).mock.calls.length).toBe(3); // SplitToGa invoked thrice + expect(GaToSplitMock).toBeCalledTimes(2); // GaToSplit invoked twice + expect(SplitToGaMock).toBeCalledTimes(3); // SplitToGa invoked thrice clearMocks(); }); diff --git a/src/integrations/ga/__tests__/GaToSplit.spec.ts b/src/integrations/ga/__tests__/GaToSplit.spec.ts index d9005ead..21c4a1ef 100644 --- a/src/integrations/ga/__tests__/GaToSplit.spec.ts +++ b/src/integrations/ga/__tests__/GaToSplit.spec.ts @@ -246,7 +246,7 @@ test('GaToSplit: `hits` flag param', () => { // send hit and assert that it was not tracked as a Split event (fakeStorage.events.track as jest.Mock).mockClear(); window.ga('send', hitSample); - expect((fakeStorage.events.track as jest.Mock).mock.calls.length).toBe(0); + expect(fakeStorage.events.track).toBeCalledTimes(0); // test teardown gaRemove(); diff --git a/src/integrations/ga/__tests__/SplitToGa.spec.ts b/src/integrations/ga/__tests__/SplitToGa.spec.ts index 33581122..849350ca 100644 --- a/src/integrations/ga/__tests__/SplitToGa.spec.ts +++ b/src/integrations/ga/__tests__/SplitToGa.spec.ts @@ -86,7 +86,7 @@ describe('SplitToGa', () => { let integration = new SplitToGa(loggerMock, {}); expect(typeof integration).toBe('object'); - expect(loggerMock.warn.mock.calls.length).toBe(0); + expect(loggerMock.warn).not.toBeCalled(); gaRemove(); expect(SplitToGa.getGa()).toBe(undefined); // should return undefined if ga command queue does not exist @@ -110,13 +110,13 @@ describe('SplitToGa', () => { const instance = new SplitToGa(loggerMock, {}) as SplitToGa; instance.queue(fakeImpression); // should queue `ga send` with the default mapped FieldsObject for impressions, appended with `splitHit` field - expect(ga.mock.calls[ga.mock.calls.length - 1]).toEqual(['send', { ...defaultImpressionFieldsObject, splitHit: true }]); + expect(ga).lastCalledWith('send', { ...defaultImpressionFieldsObject, splitHit: true }); instance.queue(fakeEvent); // should queue `ga send` with the default mapped FieldsObject for events, appended with `splitHit` field - expect(ga.mock.calls[ga.mock.calls.length - 1]).toEqual(['send', { ...defaultEventFieldsObject, splitHit: true }]); + expect(ga).lastCalledWith('send', { ...defaultEventFieldsObject, splitHit: true }); - expect(ga.mock.calls.length).toBe(2); + expect(ga).toBeCalledTimes(2); /** Custom behaviour **/ // Custom filter @@ -146,7 +146,7 @@ describe('SplitToGa', () => { [`${trackerNames[1]}.send`, { ...customMapper(), splitHit: true }] ]); // should queue `ga send` with the custom trackerName and FieldsObject from customMapper, appended with `splitHit` field - expect(ga.mock.calls.length).toBe(2); + expect(ga).toBeCalledTimes(2); // Custom mapper that returns the default FieldsObject function customMapper2(data: SplitIO.IntegrationData, defaultFieldsObject: UniversalAnalytics.FieldsObject) { @@ -158,9 +158,9 @@ describe('SplitToGa', () => { ga.mockClear(); instance3.queue(fakeImpression); // should queue `ga send` with the custom FieldsObject from customMapper2, appended with `splitHit` field - expect(ga.mock.calls[ga.mock.calls.length - 1]).toEqual(['send', { ...customMapper2(fakeImpression, defaultImpressionFieldsObject), splitHit: true }]); + expect(ga).lastCalledWith('send', { ...customMapper2(fakeImpression, defaultImpressionFieldsObject), splitHit: true }); - expect(ga.mock.calls.length).toBe(1); + expect(ga).toBeCalledTimes(1); // Custom mapper that throws an error function customMapper3() { diff --git a/src/listeners/__tests__/browser.spec.ts b/src/listeners/__tests__/browser.spec.ts index 03a98c79..32c69f59 100644 --- a/src/listeners/__tests__/browser.spec.ts +++ b/src/listeners/__tests__/browser.spec.ts @@ -118,15 +118,15 @@ test('Browser JS listener / Impressions optimized mode', (done) => { setTimeout(() => { // Unload event was triggered. Thus sendBeacon method should have been called three times. - expect((global.window.navigator.sendBeacon as jest.Mock).mock.calls.length).toBe(3); + expect(global.window.navigator.sendBeacon).toBeCalledTimes(3); // Http post services should have not been called - expect((fakeSplitApi.postTestImpressionsBulk as jest.Mock).mock.calls.length).toBe(0); - expect((fakeSplitApi.postEventsBulk as jest.Mock).mock.calls.length).toBe(0); - expect((fakeSplitApi.postTestImpressionsCount as jest.Mock).mock.calls.length).toBe(0); + expect(fakeSplitApi.postTestImpressionsBulk).not.toBeCalled(); + expect(fakeSplitApi.postEventsBulk).not.toBeCalled(); + expect(fakeSplitApi.postTestImpressionsCount).not.toBeCalled(); // pre-check and call stop - expect((global.window.removeEventListener as jest.Mock).mock.calls.length).toBe(0); + expect(global.window.removeEventListener).not.toBeCalled(); listener.stop(); // removed correct listener from correct signal on stop. @@ -149,12 +149,12 @@ test('Browser JS listener / Impressions debug mode', (done) => { setTimeout(() => { // Unload event was triggered. Thus sendBeacon method should have been called twice. - expect((global.window.navigator.sendBeacon as jest.Mock).mock.calls.length).toBe(2); + expect(global.window.navigator.sendBeacon).toBeCalledTimes(2); // Http post services should have not been called - expect((fakeSplitApi.postTestImpressionsBulk as jest.Mock).mock.calls.length).toBe(0); - expect((fakeSplitApi.postEventsBulk as jest.Mock).mock.calls.length).toBe(0); - expect((fakeSplitApi.postTestImpressionsCount as jest.Mock).mock.calls.length).toBe(0); + expect(fakeSplitApi.postTestImpressionsBulk).not.toBeCalled(); + expect(fakeSplitApi.postEventsBulk).not.toBeCalled(); + expect(fakeSplitApi.postTestImpressionsCount).not.toBeCalled(); // pre-check and call stop expect(global.window.removeEventListener).not.toBeCalled(); @@ -183,12 +183,12 @@ test('Browser JS listener / Impressions debug mode without sendBeacon API', (don setTimeout(() => { // Unload event was triggered. Thus sendBeacon method should have been called twice. - expect((sendBeacon as jest.Mock).mock.calls.length).toBe(0); + expect(sendBeacon).not.toBeCalled(); // Http post services should have not been called - expect((fakeSplitApi.postTestImpressionsBulk as jest.Mock).mock.calls.length).toBe(1); - expect((fakeSplitApi.postEventsBulk as jest.Mock).mock.calls.length).toBe(1); - expect((fakeSplitApi.postTestImpressionsCount as jest.Mock).mock.calls.length).toBe(0); + expect(fakeSplitApi.postTestImpressionsBulk).toBeCalledTimes(1); + expect(fakeSplitApi.postEventsBulk).toBeCalledTimes(1); + expect(fakeSplitApi.postTestImpressionsCount).not.toBeCalled(); // pre-check and call stop expect(global.window.removeEventListener).not.toBeCalled(); diff --git a/src/listeners/__tests__/node.spec.ts b/src/listeners/__tests__/node.spec.ts index 94f6e14c..cf5794ed 100644 --- a/src/listeners/__tests__/node.spec.ts +++ b/src/listeners/__tests__/node.spec.ts @@ -35,19 +35,19 @@ test('Node JS listener / Signal Listener SIGTERM callback with sync handler', () jest.spyOn(listener, 'stop'); // Control asserts. - expect((listener.stop as jest.Mock).mock.calls.length).toBe(0); - expect(handlerMock.mock.calls.length).toBe(0); - expect(processKillSpy.mock.calls.length).toBe(0); + expect(listener.stop).not.toBeCalled(); + expect(handlerMock).not.toBeCalled(); + expect(processKillSpy).not.toBeCalled(); // Call function // @ts-expect-error listener._sigtermHandler(); // Handler was properly called. - expect(handlerMock.mock.calls.length).toBe(1); + expect(handlerMock).toBeCalledTimes(1); // Clean up is called. - expect((listener.stop as jest.Mock).mock.calls.length).toBe(1); + expect(listener.stop).toBeCalledTimes(1); // It called for kill again, so the shutdown keeps going. expect(processKillSpy.mock.calls).toEqual([[process.pid, 'SIGTERM']]); @@ -64,21 +64,21 @@ test('Node JS listener / Signal Listener SIGTERM callback with sync handler that jest.spyOn(listener, 'stop'); // Control asserts. - expect((listener.stop as jest.Mock).mock.calls.length).toBe(0); - expect(handlerMock.mock.calls.length).toBe(0); - expect(processKillSpy.mock.calls.length).toBe(0); + expect(listener.stop).not.toBeCalled(); + expect(handlerMock).not.toBeCalled(); + expect(processKillSpy).not.toBeCalled(); // Call function. // @ts-expect-error listener._sigtermHandler(); // Handler was properly called. - expect(handlerMock.mock.calls.length).toBe(1); + expect(handlerMock).toBeCalledTimes(1); // Even if the handler throws, clean up is called. - expect((listener.stop as jest.Mock).mock.calls.length).toBe(1); + expect(listener.stop).toBeCalledTimes(1); // Even if the handler throws, it should call for kill again, so the shutdown keeps going. - expect(processKillSpy.mock.calls.length).toBe(1); + expect(processKillSpy).toBeCalledTimes(1); expect(processKillSpy.mock.calls).toEqual([[process.pid, 'SIGTERM']]); // Reset the kill spy since it's used on other tests. @@ -107,17 +107,17 @@ test('Node JS listener / Signal Listener SIGTERM callback with async handler', a listener._sigtermHandler(); // Handler was properly called. - expect(handlerMock.mock.calls.length).toBe(1); + expect(handlerMock).toBeCalledTimes(1); // Check that the wrap up is waiting for the promise to be resolved. - expect((listener.stop as jest.Mock).mock.calls.length).toBe(0); - expect(processKillSpy.mock.calls.length).toBe(0); + expect(listener.stop).not.toBeCalled(); + expect(processKillSpy).not.toBeCalled(); fakePromise.then(() => { // Clean up is called even if there is an error. - expect((listener.stop as jest.Mock).mock.calls.length).toBe(1); + expect(listener.stop).toBeCalledTimes(1); // It called for kill again, so the shutdown keeps going. - expect(processKillSpy.mock.calls.length).toBe(1); + expect(processKillSpy).toBeCalledTimes(1); expect(processKillSpy.mock.calls).toEqual([[process.pid, 'SIGTERM']]); // Reset the kill spy since it's used on other tests. @@ -151,18 +151,18 @@ test('Node JS listener / Signal Listener SIGTERM callback with async handler tha const handlerPromise = listener._sigtermHandler(); // Handler was properly called. - expect(handlerMock.mock.calls.length).toBe(1); + expect(handlerMock).toBeCalledTimes(1); // Check that the wrap up is waiting for the promise to be resolved. - expect((listener.stop as jest.Mock).mock.calls.length).toBe(0); - expect(processKillSpy.mock.calls.length).toBe(0); + expect(listener.stop).not.toBeCalled(); + expect(processKillSpy).not.toBeCalled(); // Calling .then since the wrapUp handler does not throw. (handlerPromise as Promise).then(() => { // Clean up is called. - expect((listener.stop as jest.Mock).mock.calls.length).toBe(1); + expect(listener.stop).toBeCalledTimes(1); // It called for kill again, so the shutdown keeps going. - expect(processKillSpy.mock.calls.length).toBe(1); + expect(processKillSpy).toBeCalledTimes(1); expect(processKillSpy.mock.calls).toEqual([[process.pid, 'SIGTERM']]); /* Clean up everything */ diff --git a/src/readiness/__tests__/sdkReadinessManager.spec.ts b/src/readiness/__tests__/sdkReadinessManager.spec.ts index ca032224..3cc3c765 100644 --- a/src/readiness/__tests__/sdkReadinessManager.spec.ts +++ b/src/readiness/__tests__/sdkReadinessManager.spec.ts @@ -57,7 +57,7 @@ describe('SDK Readiness Manager - Event emitter', () => { expect(sdkStatus.Event.SDK_READY_TIMED_OUT).toBe(SDK_READY_TIMED_OUT); // which contains the constants for the events, for backwards compatibility. expect(sdkStatus.Event.SDK_UPDATE).toBe(SDK_UPDATE); // which contains the constants for the events, for backwards compatibility. - expect(gateMock.once.mock.calls.length).toBe(3); // It should make three one time only subscriptions + expect(gateMock.once).toBeCalledTimes(3); // It should make three one time only subscriptions const sdkReadyResolvePromiseCall = gateMock.once.mock.calls[0]; const sdkReadyRejectPromiseCall = gateMock.once.mock.calls[1]; @@ -66,7 +66,7 @@ describe('SDK Readiness Manager - Event emitter', () => { expect(sdkReadyRejectPromiseCall[0]).toBe(SDK_READY_TIMED_OUT); // A one time only subscription is also on the SDK_READY_TIMED_OUT event, for rejecting the full blown ready promise. expect(sdkReadyFromCacheListenersCheckCall[0]).toBe(SDK_READY_FROM_CACHE); // A one time only subscription is on the SDK_READY_FROM_CACHE event, to log the event and update internal state. - expect(gateMock.on.mock.calls.length).toBe(2); // It should also add two persistent listeners + expect(gateMock.on).toBeCalledTimes(2); // It should also add two persistent listeners const removeListenerSubCall = gateMock.on.mock.calls[0]; const addListenerSubCall = gateMock.on.mock.calls[1]; @@ -81,7 +81,7 @@ describe('SDK Readiness Manager - Event emitter', () => { const readyFromCacheEventCB = gateMock.once.mock.calls[2][1]; readyFromCacheEventCB(); - expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY_FROM_CACHE event fires, we get a info message. + expect(loggerMock.info).toBeCalledTimes(1); // If the SDK_READY_FROM_CACHE event fires, we get a info message. expect(loggerMock.info).toBeCalledWith(CLIENT_READY_FROM_CACHE); // Telling us the SDK is ready to be used with data from cache. }); @@ -93,15 +93,15 @@ describe('SDK Readiness Manager - Event emitter', () => { emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls.length).toBe(1); // If the SDK_READY event fires and we have no callbacks for it (neither event nor ready promise) we get a warning. + expect(loggerMock.warn).toBeCalledTimes(1); // If the SDK_READY event fires and we have no callbacks for it (neither event nor ready promise) we get a warning. expect(loggerMock.warn).toBeCalledWith(CLIENT_NO_LISTENER); // Telling us there were no listeners and evaluations before this point may have been incorrect. - expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY event fires, we get a info message. + expect(loggerMock.info).toBeCalledTimes(1); // If the SDK_READY event fires, we get a info message. expect(loggerMock.info).toBeCalledWith(CLIENT_READY); // Telling us the SDK is ready. // Now it's marked as ready. addListenerCB('this event we do not care'); - expect(loggerMock.error.mock.calls.length).toBe(0); // Now if we add a listener to an event unrelated with readiness, we get no errors logged. + expect(loggerMock.error).not.toBeCalled(); // Now if we add a listener to an event unrelated with readiness, we get no errors logged. addListenerCB(SDK_READY); expect(loggerMock.error).toBeCalledWith(ERROR_CLIENT_LISTENER, ['SDK_READY']); // If we try to add a listener for the already emitted SDK_READY event, we get the corresponding error. @@ -118,14 +118,14 @@ describe('SDK Readiness Manager - Event emitter', () => { const addListenerCB = sdkReadinessManager.readinessManager.gate.on.mock.calls[1][1]; addListenerCB(SDK_READY); - expect(loggerMock.warn.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no warnings are logged. - expect(loggerMock.error.mock.calls.length).toBe(0); // We are adding a listener to the ready event before it is ready, so no errors are logged. + expect(loggerMock.warn).not.toBeCalled(); // We are adding a listener to the ready event before it is ready, so no warnings are logged. + expect(loggerMock.error).not.toBeCalled(); // We are adding a listener to the ready event before it is ready, so no errors are logged. emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls.length).toBe(0); // As we had at least one listener, we get no warnings. - expect(loggerMock.error.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. + expect(loggerMock.warn).not.toBeCalled(); // As we had at least one listener, we get no warnings. + expect(loggerMock.error).not.toBeCalled(); // As we had at least one listener, we get no errors. - expect(loggerMock.info.mock.calls.length).toBe(1); // If the SDK_READY event fires, we get a info message. + expect(loggerMock.info).toBeCalledTimes(1); // If the SDK_READY event fires, we get a info message. expect(loggerMock.info).toBeCalledWith(CLIENT_READY); // Telling us the SDK is ready. }); @@ -167,7 +167,7 @@ describe('SDK Readiness Manager - Event emitter', () => { removeListenerCB('random event'); emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls.length).toBe(0); // No warning when the SDK is ready as we still have one listener. + expect(loggerMock.warn).not.toBeCalled(); // No warning when the SDK is ready as we still have one listener. }); test('The event callbacks should work as expected - SDK_READY emits with expected internal callbacks', () => { @@ -184,12 +184,12 @@ describe('SDK Readiness Manager - Event emitter', () => { addListenerCB(SDK_READY); removeListenerCB(SDK_READY); - expect(loggerMock.warn.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no warnings are logged. - expect(loggerMock.error.mock.calls.length).toBe(0); // We are adding/removing listeners to the ready event before it is ready, so no errors are logged. + expect(loggerMock.warn).not.toBeCalled(); // We are adding/removing listeners to the ready event before it is ready, so no warnings are logged. + expect(loggerMock.error).not.toBeCalled(); // We are adding/removing listeners to the ready event before it is ready, so no errors are logged. emitReadyEvent(sdkReadinessManager.readinessManager); - expect(loggerMock.warn.mock.calls.length).not.toBe(0); // As we had the same amount of listeners that the expected, we get a warning. - expect(loggerMock.error.mock.calls.length).toBe(0); // As we had at least one listener, we get no errors. + expect(loggerMock.warn).toBeCalled(); // As we had the same amount of listeners that the expected, we get a warning. + expect(loggerMock.error).not.toBeCalled(); // As we had at least one listener, we get no errors. }); }); diff --git a/src/sdkClient/__tests__/sdkClientMethod.spec.ts b/src/sdkClient/__tests__/sdkClientMethod.spec.ts index 278ec615..5adc1d88 100644 --- a/src/sdkClient/__tests__/sdkClientMethod.spec.ts +++ b/src/sdkClient/__tests__/sdkClientMethod.spec.ts @@ -40,14 +40,14 @@ test.each(paramMocks)('sdkClientMethodFactory', (params) => { // `client.destroy` method should stop internal components (other client methods where validated in `client.spec.ts`) client.destroy().then(() => { - expect(params.sdkReadinessManager.readinessManager.destroy.mock.calls.length).toBe(1); + expect(params.sdkReadinessManager.readinessManager.destroy).toBeCalledTimes(1); expect(params.storage.destroy).toBeCalledTimes(1); if (params.syncManager) { expect(params.syncManager.stop).toBeCalledTimes(1); expect(params.syncManager.flush).toBeCalledTimes(1); } - if (params.signalListener) expect(params.signalListener.stop.mock.calls.length).toBe(1); + if (params.signalListener) expect(params.signalListener.stop).toBeCalledTimes(1); }); // calling the function with parameters should throw an error diff --git a/src/storages/inRedis/__tests__/ImpressionsCacheInRedis.spec.ts b/src/storages/inRedis/__tests__/ImpressionsCacheInRedis.spec.ts index 70e4724a..36892885 100644 --- a/src/storages/inRedis/__tests__/ImpressionsCacheInRedis.spec.ts +++ b/src/storages/inRedis/__tests__/ImpressionsCacheInRedis.spec.ts @@ -96,9 +96,9 @@ test('IMPRESSIONS CACHE IN REDIS / should not resolve track before calling expir // @ts-expect-error c.track([i1, i2]).then(() => { connection.quit(); // Try to disconnect right away. - expect(spy1.mock.calls.length).not.toBe(0); // Redis rpush was called once before executing external callback. + expect(spy1).toBeCalled(); // Redis rpush was called once before executing external callback. // Following assertion fails if the expire takes place after disconnected and throws unhandledPromiseRejection - expect(spy2.mock.calls.length).not.toBe(0); // Redis expire was called once before executing external callback. + expect(spy2).toBeCalled(); // Redis expire was called once before executing external callback. }).catch(e => { throw new Error(`An error was generated from the redis expire tests: ${e}`); }).then(() => { diff --git a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts index 918c895e..ba369d8c 100644 --- a/src/storages/inRedis/__tests__/RedisAdapter.spec.ts +++ b/src/storages/inRedis/__tests__/RedisAdapter.spec.ts @@ -276,7 +276,7 @@ describe('STORAGE Redis Adapter', () => { expect(ioredisMock[methodName]).toBeCalled(); // Original method (${methodName}) is called right away (through wrapper) when we are not queueing anymore. expect(instance._runningCommands.size).toBe(previousRunningCommandsSize + 1); // If the result of the operation was a thenable it will add the item to the running commands queue. - expect(timeout.mock.calls.length).toBe(previousTimeoutCalls + 1); // The promise returned by the original method should have a timeout wrapper. + expect(timeout).toBeCalledTimes(previousTimeoutCalls + 1); // The promise returned by the original method should have a timeout wrapper. // Get the original promise (the one passed to timeout) const commandTimeoutResolver = timeoutPromiseResolvers[0]; diff --git a/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts b/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts index ef1e20aa..9fb8ab89 100644 --- a/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts +++ b/src/sync/polling/syncTasks/__tests__/splitChangesUpdater.spec.ts @@ -73,11 +73,11 @@ test('splitChangesUpdater / factory', (done) => { const splitChangesUpdater = splitChangesUpdaterFactory(loggerMock, splitChangesFetcher, splitsCache, segmentsCache, readinessManager.splits, 1000, 1); splitChangesUpdater().then((result) => { - expect(setChangeNumber.mock.calls.length).toBe(1); + expect(setChangeNumber).toBeCalledTimes(1); expect(setChangeNumber).lastCalledWith(splitChangesMock1.till); - expect(addSplits.mock.calls.length).toBe(1); + expect(addSplits).toBeCalledTimes(1); expect(addSplits.mock.calls[0][0].length).toBe(splitChangesMock1.splits.length); - expect(removeSplits.mock.calls.length).toBe(1); + expect(removeSplits).toBeCalledTimes(1); expect(removeSplits).lastCalledWith([]); expect(registerSegments).toBeCalledTimes(1); expect(splitsEmitSpy).toBeCalledWith('SDK_SPLITS_ARRIVED'); diff --git a/src/sync/streaming/SSEClient/__tests__/index.spec.ts b/src/sync/streaming/SSEClient/__tests__/index.spec.ts index 0e1e3170..c660ad09 100644 --- a/src/sync/streaming/SSEClient/__tests__/index.spec.ts +++ b/src/sync/streaming/SSEClient/__tests__/index.spec.ts @@ -35,7 +35,7 @@ test('SSClient / setEventHandler, open and close methods', () => { instance.open(authDataSample); let esconnection = instance.connection; // instance of EventSource used to mock events esconnection.emitOpen(); - expect(handler.handleOpen.mock.calls.length).toBe(1); // handleOpen called when connection is opened + expect(handler.handleOpen).toBeCalledTimes(1); // handleOpen called when connection is opened handler.handleOpen.mockClear(); // emit message @@ -56,25 +56,25 @@ test('SSClient / setEventHandler, open and close methods', () => { // open attempt without open event emitted instance.open(authDataSample); - expect(handler.handleOpen.mock.calls.length).toBe(0); // handleOpen not called until open event is emitted + expect(handler.handleOpen).not.toBeCalled(); // handleOpen not called until open event is emitted // open a new connection instance.open(authDataSample); instance.connection.emitOpen(); - expect(handler.handleOpen.mock.calls.length).toBe(1); // handleOpen called when connection is open + expect(handler.handleOpen).toBeCalledTimes(1); // handleOpen called when connection is open // reopen the connection handler.handleOpen.mockClear(); instance.reopen(); instance.connection.emitOpen(); - expect(handler.handleOpen.mock.calls.length).toBe(1); // handleOpen called if connection is reopen + expect(handler.handleOpen).toBeCalledTimes(1); // handleOpen called if connection is reopen // remove event handler before opening a new connection handler.handleOpen.mockClear(); instance.setEventHandler(undefined); instance.open(authDataSample); instance.connection.emitOpen(); - expect(handler.handleOpen.mock.calls.length).toBe(0); // handleOpen not called if connection is open but the handler was removed + expect(handler.handleOpen).not.toBeCalled(); // handleOpen not called if connection is open but the handler was removed }); diff --git a/src/trackers/__tests__/eventTracker.spec.ts b/src/trackers/__tests__/eventTracker.spec.ts index 7c6b11fb..0edb462e 100644 --- a/src/trackers/__tests__/eventTracker.spec.ts +++ b/src/trackers/__tests__/eventTracker.spec.ts @@ -50,7 +50,7 @@ describe('Event Tracker', () => { const result1 = tracker.track(fakeEvent, 1); expect(fakeEventsCache.track.mock.calls[0]).toEqual([fakeEvent, 1]); // Should be present in the event cache. - expect(fakeIntegrationsManager.handleEvent.mock.calls.length).toBe(0); // The integration manager handleEvent method should not be executed synchronously. + expect(fakeIntegrationsManager.handleEvent).not.toBeCalled(); // The integration manager handleEvent method should not be executed synchronously. expect(result1).toBe(true); // Should return the value of the event cache. setTimeout(() => { @@ -65,14 +65,14 @@ describe('Event Tracker', () => { expect(tracked).toBe(false); // Should return the value of the event cache resolved promise. setTimeout(() => { - expect(fakeIntegrationsManager.handleEvent.mock.calls.length).toBe(1); // Untracked event should not be sent to integration manager. + expect(fakeIntegrationsManager.handleEvent).toBeCalledTimes(1); // Untracked event should not be sent to integration manager. const result3 = tracker.track(fakeEvent, 3) as Promise; expect(fakeEventsCache.track.mock.calls[2]).toEqual([fakeEvent, 3]); // Should be present in the event cache. result3.then(tracked => { - expect(fakeIntegrationsManager.handleEvent.mock.calls.length).toBe(1); // Tracked event should not be sent to integration manager synchronously + expect(fakeIntegrationsManager.handleEvent).toBeCalledTimes(1); // Tracked event should not be sent to integration manager synchronously expect(tracked).toBe(true); // Should return the value of the event cache resolved promise. setTimeout(() => { diff --git a/src/trackers/__tests__/impressionsTracker.spec.ts b/src/trackers/__tests__/impressionsTracker.spec.ts index 43988799..9a89a61d 100644 --- a/src/trackers/__tests__/impressionsTracker.spec.ts +++ b/src/trackers/__tests__/impressionsTracker.spec.ts @@ -55,7 +55,7 @@ describe('Impressions Tracker', () => { feature: '30', } as ImpressionDTO; - expect(fakeImpressionsCache.track.mock.calls.length).toBe(0); // cache method should not be called by just creating a tracker + expect(fakeImpressionsCache.track).not.toBeCalled(); // cache method should not be called by just creating a tracker tracker.track([imp1, imp2, imp3]); @@ -76,20 +76,20 @@ describe('Impressions Tracker', () => { fake: 'attributes' }; - expect(fakeImpressionsCache.track.mock.calls.length).toBe(0); // The storage should not be invoked if we haven't tracked impressions. - expect(fakeListener.logImpression.mock.calls.length).toBe(0); // The listener should not be invoked if we haven't tracked impressions. - expect(fakeIntegrationsManager.handleImpression.mock.calls.length).toBe(0); // The integrations manager handleImpression method should not be invoked if we haven't tracked impressions. + expect(fakeImpressionsCache.track).not.toBeCalled(); // The storage should not be invoked if we haven't tracked impressions. + expect(fakeListener.logImpression).not.toBeCalled(); // The listener should not be invoked if we haven't tracked impressions. + expect(fakeIntegrationsManager.handleImpression).not.toBeCalled(); // The integrations manager handleImpression method should not be invoked if we haven't tracked impressions. // We signal that we actually want to track the queued impressions. tracker.track([fakeImpression, fakeImpression2], fakeAttributes); expect(fakeImpressionsCache.track.mock.calls[0][0]).toEqual([fakeImpression, fakeImpression2]); // Even with a listener, impression should be sent to the cache - expect(fakeListener.logImpression.mock.calls.length).toBe(0); // The listener should not be executed synchronously. - expect(fakeIntegrationsManager.handleImpression.mock.calls.length).toBe(0); // The integrations manager handleImpression method should not be executed synchronously. + expect(fakeListener.logImpression).not.toBeCalled(); // The listener should not be executed synchronously. + expect(fakeIntegrationsManager.handleImpression).not.toBeCalled(); // The integrations manager handleImpression method should not be executed synchronously. setTimeout(() => { - expect(fakeListener.logImpression.mock.calls.length).toBe(2); // The listener should be executed after the timeout wrapping make it to the queue stack, once per each tracked impression. - expect(fakeIntegrationsManager.handleImpression.mock.calls.length).toBe(2); // The integrations manager handleImpression method should be executed after the timeout wrapping make it to the queue stack, once per each tracked impression. + expect(fakeListener.logImpression).toBeCalledTimes(2); // The listener should be executed after the timeout wrapping make it to the queue stack, once per each tracked impression. + expect(fakeIntegrationsManager.handleImpression).toBeCalledTimes(2); // The integrations manager handleImpression method should be executed after the timeout wrapping make it to the queue stack, once per each tracked impression. const impressionData1 = { impression: fakeImpression, attributes: fakeAttributes, sdkLanguageVersion: fakeMetadata.version, ip: fakeMetadata.ip, hostname: fakeMetadata.hostname }; const impressionData2 = { impression: fakeImpression2, attributes: fakeAttributes, sdkLanguageVersion: fakeMetadata.version, ip: fakeMetadata.ip, hostname: fakeMetadata.hostname }; @@ -143,7 +143,7 @@ describe('Impressions Tracker', () => { impressionsTrackerFactory(loggerMock, fakeImpressionsCache, fakeMetadata, undefined, undefined, impressionObserverCSFactory()) ]; - expect(fakeImpressionsCache.track.mock.calls.length).toBe(0); // storage method should not be called until impressions are tracked. + expect(fakeImpressionsCache.track).not.toBeCalled(); // storage method should not be called until impressions are tracked. trackers.forEach(tracker => { tracker.track([impression, impression2, impression3]); @@ -170,7 +170,7 @@ describe('Impressions Tracker', () => { const impressionCountsCache = new ImpressionCountsCacheInMemory(); const tracker = impressionsTrackerFactory(loggerMock, fakeImpressionsCache, fakeMetadata, undefined, undefined, impressionObserverCSFactory(), impressionCountsCache); - expect(fakeImpressionsCache.track.mock.calls.length).toBe(0); // cache method should not be called by just creating a tracker + expect(fakeImpressionsCache.track).not.toBeCalled(); // cache method should not be called by just creating a tracker tracker.track([impression, impression2, impression3]); diff --git a/src/utils/inputValidation/__tests__/attributes.spec.ts b/src/utils/inputValidation/__tests__/attributes.spec.ts index ae7b2c9b..e414b4ea 100644 --- a/src/utils/inputValidation/__tests__/attributes.spec.ts +++ b/src/utils/inputValidation/__tests__/attributes.spec.ts @@ -25,15 +25,15 @@ describe('INPUT VALIDATION for Attributes', () => { const validAttributes = { amIvalid: 'yes', 'are_you_sure': true, howMuch: 10 }; expect(validateAttributes(loggerMock, validAttributes, 'some_method_attrs')).toEqual(validAttributes); // It should return the passed map if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should return the passed value if it is null or undefined (since attributes are optional) without logging any errors', () => { expect(validateAttributes(loggerMock, null, 'some_method_attrs')).toBe(null); // It should return the passed null. expect(validateAttributes(loggerMock, undefined, 'some_method_attrs')).toBe(undefined); // It should return the passed undefined. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should return false and log error if attributes map is invalid', () => { @@ -46,6 +46,6 @@ describe('INPUT VALIDATION for Attributes', () => { loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); }); diff --git a/src/utils/inputValidation/__tests__/split.spec.ts b/src/utils/inputValidation/__tests__/split.spec.ts index 13ccfaa3..85d14be6 100644 --- a/src/utils/inputValidation/__tests__/split.spec.ts +++ b/src/utils/inputValidation/__tests__/split.spec.ts @@ -39,7 +39,7 @@ describe('INPUT VALIDATION for Split name', () => { expect(validateSplit(loggerMock, 'A_split-name_29', 'some_method_splitName')).toBe('A_split-name_29'); // It should return the provided string if it is valid. expect(loggerMock.error.mock.calls[0]).not.toEqual('some_method_splitName'); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should trim split name if it is a valid string with trimmable spaces and log a warning (if those are enabled)', () => { @@ -51,7 +51,7 @@ describe('INPUT VALIDATION for Split name', () => { loggerMock.warn.mockClear(); } - expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.error).not.toBeCalled(); // It should have not logged any errors. }); test('Should return false and log error if split name is not a valid string', () => { @@ -66,6 +66,6 @@ describe('INPUT VALIDATION for Split name', () => { loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); }); diff --git a/src/utils/inputValidation/__tests__/splitExistance.spec.ts b/src/utils/inputValidation/__tests__/splitExistance.spec.ts index 6b72ad87..4bc2b8e8 100644 --- a/src/utils/inputValidation/__tests__/splitExistance.spec.ts +++ b/src/utils/inputValidation/__tests__/splitExistance.spec.ts @@ -23,8 +23,8 @@ describe('Split existance (special case)', () => { expect(validateSplitExistance(loggerMock, readinessManagerMock, 'some_split', 'a label', 'test_method')).toBe(true); // Should always return true when the SDK is not ready. expect(validateSplitExistance(loggerMock, readinessManagerMock, 'some_split', LabelConstants.SPLIT_NOT_FOUND, 'test_method')).toBe(true); // Should always return true when the SDK is not ready. - expect(loggerMock.warn.mock.calls.length).toBe(0); // There should have been no warning logs since the SDK was not ready yet. - expect(loggerMock.error.mock.calls.length).toBe(0); // There should have been no error logs since the SDK was not ready yet. + expect(loggerMock.warn).not.toBeCalled(); // There should have been no warning logs since the SDK was not ready yet. + expect(loggerMock.error).not.toBeCalled(); // There should have been no error logs since the SDK was not ready yet. // Prepare the mock to fake that the SDK is ready now. (readinessManagerMock.isReady as jest.Mock).mockImplementation(() => true); @@ -32,16 +32,16 @@ describe('Split existance (special case)', () => { expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', {}, 'other_method')).toBe(true); // Should return true if it receives a Split Object instead of null (when the object is not found, for manager). expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', 'a label', 'other_method')).toBe(true); // Should return true if it receives a Label and it is not split not found (when the Split was not found on the storage, for client). - expect(loggerMock.warn.mock.calls.length).toBe(0); // There should have been no warning logs since the values we used so far were considered valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // There should have been no error logs since the values we used so far were considered valid. + expect(loggerMock.warn).not.toBeCalled(); // There should have been no warning logs since the values we used so far were considered valid. + expect(loggerMock.error).not.toBeCalled(); // There should have been no error logs since the values we used so far were considered valid. expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', null, 'other_method')).toBe(false); // Should return false if it receives a non-truthy value as a split object or label expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', undefined, 'other_method')).toBe(false); // Should return false if it receives a non-truthy value as a split object or label expect(validateSplitExistance(loggerMock, readinessManagerMock, 'other_split', LabelConstants.SPLIT_NOT_FOUND, 'other_method')).toBe(false); // Should return false if it receives a label but it is the split not found one. - expect(loggerMock.warn.mock.calls.length).toBe(3); // It should have logged 3 warnings, one per each time we called it + expect(loggerMock.warn).toBeCalledTimes(3); // It should have logged 3 warnings, one per each time we called it loggerMock.warn.mock.calls.forEach(call => expect(call).toEqual([WARN_NOT_EXISTENT_SPLIT, ['other_method', 'other_split']])); // Warning logs should have the correct message. - expect(loggerMock.error.mock.calls.length).toBe(0); // We log warnings, not errors. + expect(loggerMock.error).not.toBeCalled(); // We log warnings, not errors. }); }); diff --git a/src/utils/inputValidation/__tests__/splits.spec.ts b/src/utils/inputValidation/__tests__/splits.spec.ts index a4d51b71..221cbf1b 100644 --- a/src/utils/inputValidation/__tests__/splits.spec.ts +++ b/src/utils/inputValidation/__tests__/splits.spec.ts @@ -43,32 +43,32 @@ describe('INPUT VALIDATION for Split names', () => { const validArr = ['splitName1', 'split_name_2', 'split-name-3']; expect(validateSplits(loggerMock, validArr, 'some_method_splits')).toEqual(validArr); // It should return the provided array without changes if it is valid. - expect(validateSplitMock.mock.calls.length).toBe(validArr.length); // Should have validated each value independently. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors on the collection. + expect(validateSplitMock).toBeCalledTimes(validArr.length); // Should have validated each value independently. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors on the collection. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should return the provided array if it is a valid splits names array removing duplications, without logging any errors', () => { const validArr = ['split_name', 'split_name', 'split-name']; expect(validateSplits(loggerMock, validArr, 'some_method_splits')).toEqual(uniq(validArr)); // It should return the provided array without changes if it is valid. - expect(validateSplitMock.mock.calls.length).toBe(validArr.length); // Should have validated each value independently. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors on the collection. + expect(validateSplitMock).toBeCalledTimes(validArr.length); // Should have validated each value independently. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors on the collection. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should return false and log an error for the array if it is invalid', () => { for (let i = 0; i < invalidSplits.length; i++) { expect(validateSplits(loggerMock, invalidSplits[i], 'test_method')).toBe(false); // It will return false as the array is of an incorrect type. expect(loggerMock.error).toBeCalledWith(ERROR_EMPTY_ARRAY, ['test_method', 'split_names']); // Should log the error for the collection. - expect(validateSplitMock.mock.calls.length).toBe(0); // Should not try to validate any inner value if there is no valid array. + expect(validateSplitMock).not.toBeCalled(); // Should not try to validate any inner value if there is no valid array. loggerMock.error.mockClear(); } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should strip out any invalid value from the array', () => { @@ -82,7 +82,7 @@ describe('INPUT VALIDATION for Split names', () => { expect(validateSplitMock.mock.calls[i]).toEqual([loggerMock, myArr[i], 'test_method', 'split name']); // Should validate any inner value independently. } - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any error for the collection. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings for the collection. + expect(loggerMock.error).not.toBeCalled(); // Should not log any error for the collection. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings for the collection. }); }); diff --git a/src/utils/inputValidation/__tests__/trafficType.spec.ts b/src/utils/inputValidation/__tests__/trafficType.spec.ts index 43355676..bbea3d23 100644 --- a/src/utils/inputValidation/__tests__/trafficType.spec.ts +++ b/src/utils/inputValidation/__tests__/trafficType.spec.ts @@ -33,13 +33,13 @@ describe('INPUT VALIDATION for Traffic Types', () => { test('Should return the provided traffic type if it is a valid string without logging any errors', () => { expect(validateTrafficType(loggerMock, 'traffictype', 'some_method_trafficType')).toBe('traffictype'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. expect(validateTrafficType(loggerMock, 'traffic_type', 'some_method_trafficType')).toBe('traffic_type'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. expect(validateTrafficType(loggerMock, 'traffic-type-23', 'some_method_trafficType')).toBe('traffic-type-23'); // It should return the provided string if it is valid. - expect(loggerMock.error.mock.calls.length).toBe(0); // Should not log any errors. + expect(loggerMock.error).not.toBeCalled(); // Should not log any errors. - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); test('Should lowercase the whole traffic type if it is a valid string with uppercases and log a warning (if those are enabled)', () => { @@ -50,7 +50,7 @@ describe('INPUT VALIDATION for Traffic Types', () => { expect(loggerMock.warn.mock.calls[i]).toEqual([WARN_LOWERCASE_TRAFFIC_TYPE, ['some_method_trafficType']]); // Should log a warning. } - expect(loggerMock.error.mock.calls.length).toBe(0); // It should have not logged any errors. + expect(loggerMock.error).not.toBeCalled(); // It should have not logged any errors. }); test('Should return false and log error if traffic type is not a valid string', () => { @@ -62,6 +62,6 @@ describe('INPUT VALIDATION for Traffic Types', () => { expect(loggerMock.error.mock.calls[i]).toEqual([expectedLog, ['test_method']]); // Should log the error for the invalid traffic type. } - expect(loggerMock.warn.mock.calls.length).toBe(0); // It should have not logged any warnings. + expect(loggerMock.warn).not.toBeCalled(); // It should have not logged any warnings. }); }); diff --git a/src/utils/lang/__tests__/index.spec.ts b/src/utils/lang/__tests__/index.spec.ts index 965153b5..51a62ccc 100644 --- a/src/utils/lang/__tests__/index.spec.ts +++ b/src/utils/lang/__tests__/index.spec.ts @@ -139,7 +139,7 @@ test('LANG UTILS / find', () => { const obj = { myKey: 'myVal', myOtherKey: 'myOtherVal' }; find(obj, spy); - expect(spy.mock.calls.length === 2).toBe(true); // The iteratee should be called as many times as elements we have on the collection. + expect(spy).toBeCalledTimes(2); // The iteratee should be called as many times as elements we have on the collection. expect(spy.mock.calls[0]).toEqual(['myVal', 'myKey', obj]); // When iterating on an object the iteratee should be called with (val, key, collection) expect(spy.mock.calls[1]).toEqual(['myOtherVal', 'myOtherKey', obj]); // When iterating on an object the iteratee should be called with (val, key, collection) @@ -147,7 +147,7 @@ test('LANG UTILS / find', () => { spy.mockClear(); find(arr, spy); - expect(spy.mock.calls.length === 2).toBe(true); // The iteratee should be called as many times as elements we have on the collection. + expect(spy).toBeCalledTimes(2); // The iteratee should be called as many times as elements we have on the collection. expect(spy.mock.calls[0]).toEqual(['one', 0, arr]); // When iterating on an array the iteratee should be called with (val, index, collection) expect(spy.mock.calls[1]).toEqual(['two', 1, arr]); // When iterating on an array the iteratee should be called with (val, index, collection) @@ -486,7 +486,7 @@ test('LANG UTILS / forOwn', () => { const obj = { myKey: 'myVal', myOtherKey: 'myOtherVal' }; forOwn(obj, spy); - expect(spy.mock.calls.length === 2).toBe(true); // The iteratee should be called as many times as elements we have on the object. + expect(spy).toBeCalledTimes(2); // The iteratee should be called as many times as elements we have on the object. expect(spy.mock.calls[0]).toEqual(['myVal', 'myKey', obj]); // When iterating on an object the iteratee should be called with (val, key, collection) expect(spy.mock.calls[1]).toEqual(['myOtherVal', 'myOtherKey', obj]); // When iterating on an object the iteratee should be called with (val, key, collection) From 50301e097a23def25916bd373964d9da7fd12f3f Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 26 Mar 2021 16:37:28 -0300 Subject: [PATCH 57/58] updated package version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index a4d7edff..6619f383 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "0.0.1-beta.2", + "version": "0.0.1-beta.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d0a9df2a..f3b4817d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "0.0.1-beta.2", + "version": "0.0.1-beta.3", "description": "Split Javascript SDK common components", "main": "cjs/index.js", "module": "esm/index.js", From ea321137cb8199170fb188dbe779b291467eea84 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 26 Mar 2021 17:05:57 -0300 Subject: [PATCH 58/58] comment --- src/logger/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logger/types.ts b/src/logger/types.ts index 4cacdba8..05043be4 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -3,7 +3,7 @@ import { LogLevel } from '../types'; export interface ILoggerOptions { prefix?: string, logLevel?: LogLevel, - showLevel?: boolean, + showLevel?: boolean, // @TODO remove this param eventually since it is not being set `false` anymore } export interface ILogger {