Skip to content

Commit a5573ff

Browse files
committed
optimizely fixes
1 parent 3e3e41b commit a5573ff

File tree

10 files changed

+191
-195
lines changed

10 files changed

+191
-195
lines changed

lib/error/error_notifier.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,28 @@
1+
import { MessageResolver } from "../message/message_resolver";
12
import { sprintf } from "../utils/fns";
23
import { ErrorHandler } from "./error_handler";
34
import { OptimizelyError } from "./optimizly_error";
45

56
export interface ErrorNotifier {
6-
notify(error: OptimizelyError): void;
7+
notify(error: Error): void;
78
child(name: string): ErrorNotifier;
89
}
910

10-
export interface ErrorMessageResolver {
11-
resolve(baseMessage: string): string;
12-
}
13-
1411
export class DefaultErrorNotifier implements ErrorNotifier {
1512
private name: string;
1613
private errorHandler: ErrorHandler;
17-
private messageResolver: ErrorMessageResolver;
14+
private messageResolver: MessageResolver;
1815

19-
constructor(errorHandler: ErrorHandler, messageResolver: ErrorMessageResolver, name?: string) {
16+
constructor(errorHandler: ErrorHandler, messageResolver: MessageResolver, name?: string) {
2017
this.errorHandler = errorHandler;
2118
this.messageResolver = messageResolver;
2219
this.name = name || '';
2320
}
2421

25-
notify(error: OptimizelyError): void {
26-
const ErrorMessage = error.getErrorMessage();
27-
const resolvedBase = this.messageResolver.resolve(ErrorMessage.baseMessage);
28-
const messagePrefix = this.name ? `${this.name}: ` : '';
29-
const message = `${messagePrefix}${sprintf(resolvedBase, ...ErrorMessage.params)}`;
30-
error.setMessage(message);
22+
notify(error: Error): void {
23+
if (error instanceof OptimizelyError) {
24+
error.setMessage(this.messageResolver);
25+
}
3126
this.errorHandler.handleError(error);
3227
}
3328

lib/error/error_reporter.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,22 @@ export class ErrorReporter {
1111
this.errorNotifier = errorNotifier;
1212
}
1313

14-
report(error: OptimizelyError): void;
14+
report(error: Error): void;
1515
report(baseMessage: string, ...params: any[]): void;
1616

17-
report(error: OptimizelyError | string, ...params: any[]): void {
17+
report(error: Error | string, ...params: any[]): void {
1818
if (typeof error === 'string') {
1919
error = new OptimizelyError(error, ...params);
2020
this.report(error);
2121
return;
2222
}
2323

24-
const errorMessage = error.getErrorMessage();
25-
2624
if (this.errorNotifier) {
2725
this.errorNotifier.notify(error);
2826
}
2927

3028
if (this.logger) {
31-
this.logger.error(errorMessage.baseMessage, ...errorMessage.params);
29+
this.logger.error(error);
3230
}
3331
}
3432

lib/error/optimizly_error.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
1-
type ErrorMessage = {
2-
baseMessage: string;
3-
params: any[];
4-
};
1+
import { MessageResolver } from "../message/message_resolver";
2+
import { sprintf } from "../utils/fns";
53

64
export class OptimizelyError extends Error {
75
private baseMessage: string;
86
private params: any[];
7+
private resolved = false;
98
constructor(baseMessage: string, ...params: any[]) {
109
super();
1110
this.name = 'OptimizelyError';
1211
this.baseMessage = baseMessage;
1312
this.params = params;
1413
}
1514

16-
getErrorMessage(): ErrorMessage {
17-
return {
18-
baseMessage: this.baseMessage,
19-
params: this.params,
20-
};
21-
}
15+
getMessage(resolver?: MessageResolver): string {
16+
if (this.resolved) {
17+
return this.message;
18+
}
19+
20+
if (resolver) {
21+
this.setMessage(resolver);
22+
return this.message;
23+
}
2224

23-
setMessage(message: string): void {
24-
this.message = message;
25+
return this.baseMessage;
26+
}
27+
28+
setMessage(resolver: MessageResolver): void {
29+
this.message = sprintf(resolver.resolve(this.baseMessage), ...this.params);
30+
this.resolved = true;
2531
}
2632
}

lib/error_messages.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const CONDITION_EVALUATOR_ERROR = '%s: Error evaluating audience conditio
1919
export const DATAFILE_AND_SDK_KEY_MISSING =
2020
'%s: You must provide at least one of sdkKey or datafile. Cannot start Optimizely';
2121
export const EXPERIMENT_KEY_NOT_IN_DATAFILE = '%s: Experiment key %s is not in datafile.';
22-
export const FEATURE_NOT_IN_DATAFILE = '%s: Feature key %s is not in datafile.';
22+
export const FEATURE_NOT_IN_DATAFILE = 'Feature key %s is not in datafile.';
2323
export const FETCH_SEGMENTS_FAILED_NETWORK_ERROR = '%s: Audience segments fetch failed. (network error)';
2424
export const FETCH_SEGMENTS_FAILED_DECODE_ERROR = '%s: Audience segments fetch failed. (decode error)';
2525
export const IMPROPERLY_FORMATTED_EXPERIMENT = '%s: Experiment key %s is improperly formatted.';
@@ -33,7 +33,7 @@ export const INVALID_ERROR_HANDLER = '%s: Provided "errorHandler" is in an inval
3333
export const INVALID_EVENT_DISPATCHER = '%s: Provided "eventDispatcher" is in an invalid format.';
3434
export const INVALID_EVENT_TAGS = '%s: Provided event tags are in an invalid format.';
3535
export const INVALID_EXPERIMENT_KEY =
36-
'%s: Experiment key %s is not in datafile. It is either invalid, paused, or archived.';
36+
'Experiment key %s is not in datafile. It is either invalid, paused, or archived.';
3737
export const INVALID_EXPERIMENT_ID = '%s: Experiment ID %s is not in datafile.';
3838
export const INVALID_GROUP_ID = '%s: Group ID %s is not in datafile.';
3939
export const INVALID_LOGGER = '%s: Provided "logger" is in an invalid format.';
@@ -105,4 +105,12 @@ export const UNABLE_TO_GET_VUID_VUID_MANAGER_NOT_AVAILABLE = 'Unable to get VUID
105105
export const UNKNOWN_CONDITION_TYPE =
106106
'%s: Audience condition %s has an unknown condition type. You may need to upgrade to a newer release of the Optimizely SDK.';
107107
export const UNKNOWN_MATCH_TYPE =
108-
'%s: Audience condition %s uses an unknown match type. You may need to upgrade to a newer release of the Optimizely SDK.';
108+
'%s: Audience condition %s uses an unknown match type. You may need to upgrade to a newer release of the Optimizely SDK.';
109+
export const UNRECOGNIZED_DECIDE_OPTION = 'Unrecognized decide option %s provided.';
110+
export const INVALID_OBJECT = 'Optimizely object is not valid. Failing %s.';
111+
export const EVENT_KEY_NOT_FOUND = 'Event key %s is not in datafile.';
112+
export const NOT_TRACKING_USER = 'Not tracking user %s.';
113+
export const VARIABLE_REQUESTED_WITH_WRONG_TYPE =
114+
'Requested variable type "%s", but variable is of type "%s". Use correct API to retrieve value. Returning None.';
115+
116+
export const messages: string[] = [];

lib/log_messages.ts

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,18 @@ export const ACTIVATE_USER = '%s: Activating user %s in experiment %s.';
1818
export const DISPATCH_CONVERSION_EVENT = '%s: Dispatching conversion event to URL %s with params %s.';
1919
export const DISPATCH_IMPRESSION_EVENT = '%s: Dispatching impression event to URL %s with params %s.';
2020
export const DEPRECATED_EVENT_VALUE = '%s: Event value is deprecated in %s call.';
21-
export const EVENT_KEY_NOT_FOUND = '%s: Event key %s is not in datafile.';
2221
export const EXPERIMENT_NOT_RUNNING = '%s: Experiment %s is not running.';
23-
export const FEATURE_ENABLED_FOR_USER = '%s: Feature %s is enabled for user %s.';
24-
export const FEATURE_NOT_ENABLED_FOR_USER = '%s: Feature %s is not enabled for user %s.';
22+
export const FEATURE_ENABLED_FOR_USER = 'Feature %s is enabled for user %s.';
23+
export const FEATURE_NOT_ENABLED_FOR_USER = 'Feature %s is not enabled for user %s.';
2524
export const FEATURE_HAS_NO_EXPERIMENTS = '%s: Feature %s is not attached to any experiments.';
2625
export const FAILED_TO_PARSE_VALUE = '%s: Failed to parse event value "%s" from event tags.';
2726
export const FAILED_TO_PARSE_REVENUE = '%s: Failed to parse revenue value "%s" from event tags.';
2827
export const FORCED_BUCKETING_FAILED = '%s: Variation key %s is not in datafile. Not activating user %s.';
29-
export const INVALID_OBJECT = '%s: Optimizely object is not valid. Failing %s.';
30-
export const INVALID_CLIENT_ENGINE = '%s: Invalid client engine passed: %s. Defaulting to node-sdk.';
28+
export const INVALID_CLIENT_ENGINE = 'Invalid client engine passed: %s. Defaulting to node-sdk.';
3129
export const INVALID_DEFAULT_DECIDE_OPTIONS = '%s: Provided default decide options is not an array.';
32-
export const INVALID_DECIDE_OPTIONS = '%s: Provided decide options is not an array. Using default decide options.';
30+
export const INVALID_DECIDE_OPTIONS = 'Provided decide options is not an array. Using default decide options.';
3331
export const NO_ROLLOUT_EXISTS = '%s: There is no rollout of feature %s.';
34-
export const NOT_ACTIVATING_USER = '%s: Not activating user %s for experiment %s.';
35-
export const NOT_TRACKING_USER = '% s: Not tracking user %s.';
32+
export const NOT_ACTIVATING_USER = 'Not activating user %s for experiment %s.';
3633
export const ODP_DISABLED = 'ODP Disabled.';
3734
export const ODP_IDENTIFY_FAILED_ODP_DISABLED = '%s: ODP identify event for user %s is not dispatched (ODP disabled).';
3835
export const ODP_IDENTIFY_FAILED_ODP_NOT_INTEGRATED =
@@ -48,10 +45,9 @@ export const SAVED_USER_VARIATION = '%s: Saved user profile for user "%s".';
4845
export const UPDATED_USER_VARIATION = '%s: Updated variation "%s" of experiment "%s" for user "%s".';
4946
export const SAVED_VARIATION_NOT_FOUND =
5047
'%s: User %s was previously bucketed into variation with ID %s for experiment %s, but no matching variation was found.';
51-
export const SHOULD_NOT_DISPATCH_ACTIVATE = '%s: Experiment %s is not in "Running" state. Not activating user.';
48+
export const SHOULD_NOT_DISPATCH_ACTIVATE = 'Experiment %s is not in "Running" state. Not activating user.';
5249
export const SKIPPING_JSON_VALIDATION = '%s: Skipping JSON schema validation.';
53-
export const TRACK_EVENT = '%s: Tracking event %s for user %s.';
54-
export const UNRECOGNIZED_DECIDE_OPTION = '%s: Unrecognized decide option %s provided.';
50+
export const TRACK_EVENT = 'Tracking event %s for user %s.';
5551
export const USER_BUCKETED_INTO_TARGETING_RULE = '%s: User %s bucketed into targeting rule %s.';
5652
export const USER_IN_FEATURE_EXPERIMENT = '%s: User %s is in variation %s of experiment %s on the feature %s.';
5753
export const USER_IN_ROLLOUT = '%s: User %s is in rollout of feature %s.';
@@ -84,17 +80,16 @@ export const USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT =
8480
export const USER_NOT_IN_EXPERIMENT = '%s: User %s does not meet conditions to be in experiment %s.';
8581
export const USER_NOT_IN_ROLLOUT = '%s: User %s is not in rollout of feature %s.';
8682
export const USER_RECEIVED_DEFAULT_VARIABLE_VALUE =
87-
'%s: User "%s" is not in any variation or rollout rule. Returning default value for variable "%s" of feature flag "%s".';
83+
'User "%s" is not in any variation or rollout rule. Returning default value for variable "%s" of feature flag "%s".';
8884
export const FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE =
89-
'%s: Feature "%s" is not enabled for user %s. Returning the default variable value "%s".';
85+
'Feature "%s" is not enabled for user %s. Returning the default variable value "%s".';
9086
export const VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE =
91-
'%s: Variable "%s" is not used in variation "%s". Returning default value.';
92-
export const USER_RECEIVED_VARIABLE_VALUE = '%s: Got variable value "%s" for variable "%s" of feature flag "%s"';
87+
'Variable "%s" is not used in variation "%s". Returning default value.';
88+
export const USER_RECEIVED_VARIABLE_VALUE = 'Got variable value "%s" for variable "%s" of feature flag "%s"';
9389
export const VALID_DATAFILE = '%s: Datafile is valid.';
94-
export const VALID_USER_PROFILE_SERVICE = '%s: Valid user profile service provided.';
90+
export const VALID_USER_PROFILE_SERVICE = 'Valid user profile service provided.';
9591
export const VARIATION_REMOVED_FOR_USER = '%s: Variation mapped to experiment %s has been removed for user %s.';
96-
export const VARIABLE_REQUESTED_WITH_WRONG_TYPE =
97-
'%s: Requested variable type "%s", but variable is of type "%s". Use correct API to retrieve value. Returning None.';
92+
9893
export const VALID_BUCKETING_ID = '%s: BucketingId is valid: "%s"';
9994
export const BUCKETING_ID_NOT_STRING = '%s: BucketingID attribute is not a string. Defaulted to userId';
10095
export const EVALUATING_AUDIENCE = '%s: Starting to evaluate audience "%s" with conditions: %s.';
@@ -109,7 +104,7 @@ export const UNEXPECTED_TYPE =
109104
'%s: Audience condition %s evaluated to UNKNOWN because a value of type "%s" was passed for user attribute "%s".';
110105
export const UNEXPECTED_TYPE_NULL =
111106
'%s: Audience condition %s evaluated to UNKNOWN because a null value was passed for user attribute "%s".';
112-
export const UPDATED_OPTIMIZELY_CONFIG = '%s: Updated Optimizely config to revision %s (project id %s)';
107+
export const UPDATED_OPTIMIZELY_CONFIG = 'Updated Optimizely config to revision %s (project id %s)';
113108
export const OUT_OF_BOUNDS =
114109
'%s: Audience condition %s evaluated to UNKNOWN because the number value for user attribute "%s" is not in the range [-2^53, +2^53].';
115110
export const UNABLE_TO_ATTACH_UNLOAD = '%s: unable to bind optimizely.close() to page unload event: "%s"';
@@ -119,3 +114,4 @@ export const MAKING_DATAFILE_REQ_TO_URL_WITH_HEADERS = 'Making datafile request
119114
export const RESPONSE_STATUS_CODE = 'Response status code: %s';
120115
export const SAVED_LAST_MODIFIED_HEADER_VALUE_FROM_RESPONSE = 'Saved last modified header value from response: %s';
121116

117+
export const messages: string[] = [];

lib/logging/logger.ts

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
import { OptimizelyError } from '../error/optimizly_error';
17+
import { MessageResolver } from '../message/message_resolver';
1618
import { sprintf } from '../utils/fns'
1719

1820
export enum LogLevel {
@@ -23,16 +25,15 @@ export enum LogLevel {
2325
}
2426

2527
export interface LoggerFacade {
26-
log(logLevel: LogLevel, message: string | Error, ...splat: any[]): void;
27-
info(message: string | Error, ...splat: any[]): void;
28-
debug(message: string | Error, ...splat: any[]): void;
29-
warn(message: string | Error, ...splat: any[]): void;
30-
error(message: string | Error, ...splat: any[]): void;
28+
info(message: string | Error, ...args: any[]): void;
29+
debug(message: string | Error, ...args: any[]): void;
30+
warn(message: string | Error, ...args: any[]): void;
31+
error(message: string | Error, ...args: any[]): void;
3132
child(name: string): LoggerFacade;
3233
}
3334

3435
export interface LogHandler {
35-
log(level: LogLevel, message: string, ...splat: any[]): void
36+
log(level: LogLevel, message: string, ...args: any[]): void
3637
}
3738

3839
export class ConsoleLogHandler implements LogHandler {
@@ -58,14 +59,10 @@ export class ConsoleLogHandler implements LogHandler {
5859
}
5960
}
6061

61-
export interface LogResolver {
62-
log(msg: string): string;
63-
err(msg: string): string;
64-
}
65-
6662
type OptimizelyLoggerConfig = {
6763
logHandler: LogHandler,
68-
logResolver?: LogResolver,
64+
infoMsgResolver?: MessageResolver,
65+
errorMsgResolver: MessageResolver,
6966
level: LogLevel,
7067
name?: string,
7168
};
@@ -74,12 +71,14 @@ export class OptimizelyLogger implements LoggerFacade {
7471
private name?: string;
7572
private prefix: string;
7673
private logHandler: LogHandler;
77-
private logResolver?: LogResolver;
74+
private infoResolver?: MessageResolver;
75+
private errorResolver: MessageResolver;
7876
private level: LogLevel;
7977

8078
constructor(config: OptimizelyLoggerConfig) {
8179
this.logHandler = config.logHandler;
82-
this.logResolver = config.logResolver;
80+
this.infoResolver = config.infoMsgResolver;
81+
this.errorResolver = config.errorMsgResolver;
8382
this.level = config.level;
8483
this.name = config.name;
8584
this.prefix = this.name ? `${this.name}: ` : '';
@@ -88,53 +87,57 @@ export class OptimizelyLogger implements LoggerFacade {
8887
child(name: string): OptimizelyLogger {
8988
return new OptimizelyLogger({
9089
logHandler: this.logHandler,
91-
logResolver: this.logResolver,
90+
infoMsgResolver: this.infoResolver,
91+
errorMsgResolver: this.errorResolver,
9292
level: this.level,
9393
name: `${this.name}.${name}`,
9494
});
9595
}
9696

97-
info(message: string | Error, ...splat: any[]): void {
98-
this.log(LogLevel.Info, message, ...splat)
97+
info(message: string | Error, ...args: any[]): void {
98+
this.log(LogLevel.Info, message, args)
9999
}
100100

101-
debug(message: string | Error, ...splat: any[]): void {
102-
this.log(LogLevel.Debug, message, ...splat)
101+
debug(message: string | Error, ...args: any[]): void {
102+
this.log(LogLevel.Debug, message, args)
103103
}
104104

105-
warn(message: string | Error, ...splat: any[]): void {
106-
this.log(LogLevel.Warn, message, ...splat)
105+
warn(message: string | Error, ...args: any[]): void {
106+
this.log(LogLevel.Warn, message, args)
107107
}
108108

109-
error(message: string | Error, ...splat: any[]): void {
110-
this.log(LogLevel.Error, message, ...splat)
109+
error(message: string | Error, ...args: any[]): void {
110+
this.log(LogLevel.Error, message, args)
111111
}
112112

113-
private handleLog(level: LogLevel, message: string, ...splat: any[]) {
114-
const log = `${this.prefix}${sprintf(message, splat)}`
113+
private handleLog(level: LogLevel, message: string, args: any[]) {
114+
const log = `${this.prefix}${sprintf(message, ...args)}`
115115
this.logHandler.log(level, log);
116116
}
117117

118-
log(level: LogLevel, message: string | Error, ...splat: any[]): void {
118+
private log(level: LogLevel, message: string | Error, ...args: any[]): void {
119119
if (level < this.level) {
120120
return;
121121
}
122122

123123
if (message instanceof Error) {
124-
this.handleLog(level, message.toString());
124+
if (message instanceof OptimizelyError) {
125+
message.setMessage(this.errorResolver);
126+
}
127+
this.handleLog(level, message.message, []);
125128
return;
126129
}
127130

128-
if (!this.logResolver) {
129-
this.handleLog(level, message, ...splat);
130-
return;
131-
}
131+
let resolver = this.errorResolver;
132132

133-
const resolvedMessage = level < LogLevel.Warn ? this.logResolver.log(message)
134-
: this.logResolver.err(message);
135-
136-
if (resolvedMessage) {
137-
this.handleLog(level, resolvedMessage, ...splat);
133+
if (level < LogLevel.Warn) {
134+
if (!this.infoResolver) {
135+
return;
136+
}
137+
resolver = this.infoResolver;
138138
}
139+
140+
const resolvedMessage = resolver.resolve(message);
141+
this.handleLog(level, resolvedMessage, args);
139142
}
140143
}

lib/message/message_resolver.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { messages as infoMessages } from '../log_messages';
2+
import { messages as errorMessages } from '../error_messages';
3+
4+
export interface MessageResolver {
5+
resolve(baseMessage: string): string;
6+
}
7+
8+
export const infoResolver: MessageResolver = {
9+
resolve(baseMessage: string): string {
10+
const messageNum = parseInt(baseMessage);
11+
return infoMessages[messageNum] || baseMessage;
12+
}
13+
};
14+
15+
export const errorResolver: MessageResolver = {
16+
resolve(baseMessage: string): string {
17+
const messageNum = parseInt(baseMessage);
18+
return errorMessages[messageNum] || baseMessage;
19+
}
20+
};

0 commit comments

Comments
 (0)