Skip to content

Commit 1d8e2d4

Browse files
Kroach/oasis 1706 numeric (#174)
* Add OPTLYEventMetricNameValue * Promote OPTLYEventMetric 'long value' to 'NSNumber *value' * Factor out revenueValue:value: * Add numericValue:value: and 3 new NSString constants to OPTLYLoggerMessages.m+.h * kEventValue --> kEventRevenue in OPTLYEventBuilderTest.m * Adding more '#pragma mark's to OPTLYEventBuilderTest.m * Add testBuildEventTicketWithValue * Clarify purpose of 3 'revenue' tests with comments and better names * Add testBuildEventTicketWithStringValue . Fix numericValue:value: bug. * Add testBuildEventTicketWithNANValue and testBuildEventTicketWithINFINITYValue * Add testBuildEventTicketWithTooLargeDoubleRevenue and improve revenueValue:value: * Add testBuildEventTicketWithInvalidObjectValue * Improve 3 tests and fix 2 mistakes in numericValue:value: * Add 'Check eventMatrics details' to 2 tests and update createEventMetrics:eventTags: * Add testBuildEventTicketWithHugeUnsignedLongLongRevenue . Wax and shine revenueValue:value: . * Use 'for (NSDictionary *eventMetric in eventMetrics)' in checkEventTicket:... * Refactor similar code into checkEventMetricsDetails:... subroutine. * Improve test rigor with 4 more calls to checkEventMetricsDetails:... * Improve flexibility of checkEventMetricsDetails:... * Improve test rigor with 6 more calls to checkEventMetricsDetails:... * Improve test rigor with 3 more calls to checkEventMetricsDetails:... * Add commonBuildEventTicketTest:sentEventTags: and refactor many testBuildEventXxx * Add 8 more test methods to allowed and disallowed boundary cases. * NSAssert --> XCTAssert in OPTLYEventBuilderTest.m * Add testBuildEventTicketWithRevenueAndValue * OASIS-1706 Numeric metrics support in SDK Summary: Numeric metrics support in SDK The shortest summary possible is "Add new 'value' event key that allows 'double' values similar to the preexisting 'revenue' event key that allows 'long long' values and 'revenue' is retained." Add OPTLYEventMetricNameValue Promote OPTLYEventMetric 'long value' to 'NSNumber *value' Factor out revenueValue:value: Add numericValue:value: and 3 new NSString constants to OPTLYLoggerMessages.m+.h kEventValue --> kEventRevenue in OPTLYEventBuilderTest.m Adding more '#pragma mark's to OPTLYEventBuilderTest.m Add testBuildEventTicketWithValue Clarify purpose of 3 'revenue' tests with comments and better names Add testBuildEventTicketWithStringValue . Fix numericValue:value: bug. Add testBuildEventTicketWithNANValue and testBuildEventTicketWithINFINITYValue Add testBuildEventTicketWithTooLargeDoubleRevenue and improve revenueValue:value: Add testBuildEventTicketWithInvalidObjectValue Improve 3 tests and fix 2 mistakes in numericValue:value: Add 'Check eventMatrics details' to 2 tests and update createEventMetrics:eventTags: Add testBuildEventTicketWithHugeUnsignedLongLongRevenue . Wax and shine revenueValue:value: . Merge branch 'master' into kroach/OASIS-1706-numeric Use 'for (NSDictionary *eventMetric in eventMetrics)' in checkEventTicket:... Refactor similar code into checkEventMetricsDetails:... subroutine. Improve test rigor with 4 more calls to checkEventMetricsDetails:... Improve flexibility of checkEventMetricsDetails:... Improve test rigor with 6 more calls to checkEventMetricsDetails:... Improve test rigor with 3 more calls to checkEventMetricsDetails:... Add commonBuildEventTicketTest:sentEventTags: and refactor many testBuildEventXxx Add 8 more test methods to allowed and disallowed boundary cases. NSAssert --> XCTAssert in OPTLYEventBuilderTest.m Add testBuildEventTicketWithRevenueAndValue Rebuild 2 universal frameworks Test Plan: * 8 iOS test suites PASSED [from (10) above] * OptimizelySDKiOSUniversalTests PASSED * OptimizelySDKiOS Product > Analyze PASSED * OptimizelyiOSDemoApp PASSED * 7 tvOS test suites PASSED * OptimizelySDKTVOSUniversalTests PASSED * OptimizelyTVOSDemoApp PASSED * sh ./Scripts/local_travis.sh PASSED Reviewers: alda JIRA Issues: OASIS-1706 Differential Revision: https://phabricator.optimizely.com/D17497 * ARM 'IEEE 754 arithmetic' comment * Add 'char' and 'unsigned char' cases to 'if' test in OPTLYEventBuilder.m * Add OPTLYLoggerMessagesRevenueValueIntegerOverflow and OPTLYLoggerMessagesRevenueValueFloatOverflow * OPTLYEventBuilder.m comments * Cast should have been to (NSString*) * Add OPTLYLoggerMessagesNumericValueString * Adopt testRevenueMetricXxx and testValueMetricXxx method names * Add 'bool' type to 'if' test * Disallow 'boolean' NSNumber's. Add testObjectiveCBooleans and testValueMetricWithBoolean . * Add testObjectiveCCharNSNumbers
1 parent cdda031 commit 1d8e2d4

File tree

14 files changed

+735
-324
lines changed

14 files changed

+735
-324
lines changed

OptimizelySDKCore/OptimizelySDKCore/OPTLYEventBuilder.m

Lines changed: 149 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,132 @@ - (NSDictionary *)buildDecisionEventTicket:(OPTLYProjectConfig *)config
9393
return [params copy];
9494
}
9595

96+
- (NSNumber *)revenueValue:(OPTLYProjectConfig *)config value:(NSObject *)value {
97+
// Convert value to NSNumber of type "long long" or nil (failure) if impossible.
98+
NSNumber *answer = nil;
99+
// If the object is an in range NSNumber, then char, floats, and boolean values will be cast to a "long long".
100+
if ([value isKindOfClass:[NSNumber class]]) {
101+
answer = (NSNumber*)value;
102+
const char *objCType = [answer objCType];
103+
// Dispatch objCType according to one of "Type Encodings" listed here:
104+
// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
105+
if ((strcmp(objCType, @encode(bool)) == 0)
106+
|| [value isEqual:@YES]
107+
|| [value isEqual:@NO]) {
108+
// NSNumber's generated by "+ (NSNumber *)numberWithBool:(BOOL)value;"
109+
// serialize to JSON booleans "true" and "false" via NSJSONSerialization .
110+
// The @YES and @NO compile to __NSCFBoolean's which (strangely enough)
111+
// are ((strcmp(objCType, @encode(char)) == 0) but these serialize as
112+
// JSON booleans "true" and "false" instead of JSON numbers.
113+
// These aren't integers, so shouldn't be sent.
114+
answer = nil;
115+
[config.logger logMessage:OPTLYLoggerMessagesRevenueValueInvalidBoolean withLevel:OptimizelyLogLevelWarning];
116+
} else if ((strcmp(objCType, @encode(char)) == 0)
117+
|| (strcmp(objCType, @encode(unsigned char)) == 0)
118+
|| (strcmp(objCType, @encode(short)) == 0)
119+
|| (strcmp(objCType, @encode(unsigned short)) == 0)
120+
|| (strcmp(objCType, @encode(int)) == 0)
121+
|| (strcmp(objCType, @encode(unsigned int)) == 0)
122+
|| (strcmp(objCType, @encode(long)) == 0)
123+
|| (strcmp(objCType, @encode(long long)) == 0)) {
124+
// These objCType's all fit inside "long long"
125+
} else if (((strcmp(objCType, @encode(unsigned long)) == 0)
126+
|| (strcmp(objCType, @encode(unsigned long long)) == 0))) {
127+
// Cast in range "unsigned long" and "unsigned long long" to "long long".
128+
// NOTE: Above uses all 64 bits of precision available and that "unsigned long"
129+
// and "unsigned long long" are same size on 64 bit Apple platforms.
130+
// https://developer.apple.com/library/content/documentation/General/Conceptual/CocoaTouch64BitGuide/Major64-BitChanges/Major64-BitChanges.html
131+
if ([answer unsignedLongLongValue]<=((unsigned long long)LLONG_MAX)) {
132+
long long longLongValue = [answer longLongValue];
133+
answer = [NSNumber numberWithLongLong:longLongValue];
134+
} else {
135+
// The unsignedLongLongValue is outside of [LLONG_MIN,LLONG_MAX], so
136+
// can't be properly cast to "long long" nor will be sent.
137+
answer = nil;
138+
[config.logger logMessage:OPTLYLoggerMessagesRevenueValueIntegerOverflow withLevel:OptimizelyLogLevelWarning];
139+
}
140+
} else if ((LLONG_MIN<=[answer doubleValue])&&([answer doubleValue]<=LLONG_MAX)) {
141+
// Cast in range floats etc. to long long, rounding or trunctating fraction parts.
142+
// NOTE: Mantissas of Objective-C doubles have 53 bits of precision which is
143+
// less than the 64 bits of precision of a "long long" or "unsigned long".
144+
// OTOH, floats have expts which can put the value of float outside the range
145+
// of a "long long" or "unsigned long". Therefore, we test doubleValue
146+
// -- the highest precision floating format made available by NSNumber --
147+
// against [LLONG_MIN,LLONG_MAX] only after we're guaranteed we've already
148+
// considered all possible NSNumber integer formats (the previous two "if"
149+
// conditions).
150+
// https://en.wikipedia.org/wiki/IEEE_754
151+
// Intel "Floating-point Formats"
152+
// https://software.intel.com/en-us/node/523338
153+
// ARM "IEEE 754 arithmetic"
154+
// https://developer.arm.com/docs/dui0808/g/floating-point-support/ieee-754-arithmetic
155+
answer = @([answer longLongValue]);
156+
// Appropriate warning since conversion to integer generally will lose
157+
// some non-zero fraction after the decimal point. Even if the fraction is zero,
158+
// the warning could alert user of SDK to a coding issue that should be remedied.
159+
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesRevenueValueFloatOverflow, value, answer] withLevel:OptimizelyLogLevelWarning];
160+
} else {
161+
// all other NSNumber's can't be reasonably cast to long long
162+
answer = nil;
163+
[config.logger logMessage:OPTLYLoggerMessagesRevenueValueInvalid withLevel:OptimizelyLogLevelWarning];
164+
}
165+
} else if ([value isKindOfClass:[NSString class]]) {
166+
// cast strings to long long
167+
answer = @([(NSString*)value longLongValue]);
168+
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesRevenueValueString, value] withLevel:OptimizelyLogLevelWarning];
169+
} else {
170+
// all other objects can't be cast to long long
171+
[config.logger logMessage:OPTLYLoggerMessagesRevenueValueInvalid withLevel:OptimizelyLogLevelWarning];
172+
};
173+
return answer;
174+
}
175+
176+
- (NSNumber *)numericValue:(OPTLYProjectConfig *)config value:(NSObject *)value {
177+
// Convert value to NSNumber of type "double" or nil (failure) if impossible.
178+
NSNumber *answer = nil;
179+
// if the object is an NSNumber, then char, floats, and boolean values will be cast to a double int
180+
if ([value isKindOfClass:[NSNumber class]]) {
181+
answer = (NSNumber*)value;
182+
const char *objCType = [answer objCType];
183+
// Dispatch objCType according to one of "Type Encodings" listed here:
184+
// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
185+
if ((strcmp(objCType, @encode(bool)) == 0)
186+
|| [value isEqual:@YES]
187+
|| [value isEqual:@NO]) {
188+
// NSNumber's generated by "+ (NSNumber *)numberWithBool:(BOOL)value;"
189+
// serialize to JSON booleans "true" and "false" via NSJSONSerialization .
190+
// The @YES and @NO compile to __NSCFBoolean's which (strangely enough)
191+
// are ((strcmp(objCType, @encode(char)) == 0) but these serialize as
192+
// JSON booleans "true" and "false" instead of JSON numbers.
193+
// These aren't integers, so shouldn't be sent.
194+
answer = nil;
195+
[config.logger logMessage:OPTLYLoggerMessagesNumericValueInvalidBoolean withLevel:OptimizelyLogLevelWarning];
196+
} else {
197+
// Require real numbers (not infinite or NaN).
198+
double doubleValue = [(NSNumber*)value doubleValue];
199+
if (isfinite(doubleValue)) {
200+
answer = (NSNumber*)value;
201+
} else {
202+
answer = nil;
203+
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesNumericValueInvalidFloat, value] withLevel:OptimizelyLogLevelWarning];
204+
}
205+
}
206+
} else if ([value isKindOfClass:[NSString class]]) {
207+
// cast strings to double
208+
double doubleValue = [(NSString*)value doubleValue];
209+
if (isfinite(doubleValue)) {
210+
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesNumericValueString, value] withLevel:OptimizelyLogLevelWarning];
211+
answer = [NSNumber numberWithDouble:doubleValue];
212+
} else {
213+
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesNumericValueInvalidString, value] withLevel:OptimizelyLogLevelWarning];
214+
}
215+
} else {
216+
// all other objects can't be cast to double
217+
[config.logger logMessage:OPTLYLoggerMessagesNumericValueInvalid withLevel:OptimizelyLogLevelWarning];
218+
};
219+
return answer;
220+
}
221+
96222
- (NSDictionary *)buildEventTicket:(OPTLYProjectConfig *)config
97223
bucketer:(id<OPTLYBucketer>)bucketer
98224
userId:(NSString *)userId
@@ -119,41 +245,28 @@ - (NSDictionary *)buildEventTicket:(OPTLYProjectConfig *)config
119245
return nil;
120246
}
121247

122-
// Allow only 'revenue' eventTags with integer values (max long long); otherwise the value will be cast to an integer
123248
NSMutableDictionary *mutableEventTags = [[NSMutableDictionary alloc] initWithDictionary:eventTags];
124249

125250
if ([[eventTags allKeys] containsObject:OPTLYEventMetricNameRevenue]) {
126-
127-
id revenueValue = eventTags[OPTLYEventMetricNameRevenue];
128-
129-
// if the object is an NSNumber, then char, floats, and boolean values will be cast to a long long int
130-
if ([revenueValue isKindOfClass:[NSNumber class]]) {
131-
if (!(strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(short)) == 0 ||
132-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(int)) == 0 ||
133-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(long)) == 0 ||
134-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(long long)) == 0 ||
135-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned short)) == 0 ||
136-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned int)) == 0 ||
137-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned long)) == 0 ||
138-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned long long)) == 0)) {
139-
NSNumber *revenueValue = eventTags[OPTLYEventMetricNameRevenue];
140-
long long revenueValueCast = [revenueValue longLongValue];
141-
mutableEventTags[OPTLYEventMetricNameRevenue] = [NSNumber numberWithLongLong:revenueValueCast];
142-
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesReveneuValueInvalidInteger, revenueValueCast] withLevel:OptimizelyLogLevelWarning];
143-
}
144-
// cast strings to int
145-
} else if ([revenueValue isKindOfClass:[NSString class]]) {
146-
NSNumber *revenueValue = eventTags[OPTLYEventMetricNameRevenue];
147-
long long revenueValueCast = [revenueValue longLongValue];
148-
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesRevenueValueString, revenueValueCast] withLevel:OptimizelyLogLevelWarning];
149-
mutableEventTags[OPTLYEventMetricNameRevenue] = [NSNumber numberWithLongLong:revenueValueCast];
150-
// all other objects can't be cast to an integer
251+
// Allow only 'revenue' eventTags with integer values (max long long); otherwise the value will be cast to an integer
252+
NSNumber *revenueValue = [self revenueValue:config value:eventTags[OPTLYEventMetricNameRevenue]];
253+
if (revenueValue != nil) {
254+
mutableEventTags[OPTLYEventMetricNameRevenue] = revenueValue;
151255
} else {
152-
[config.logger logMessage:OPTLYLoggerMessagesRevenueValueInvalid withLevel:OptimizelyLogLevelWarning];
153256
[mutableEventTags removeObjectForKey:OPTLYEventMetricNameRevenue];
154257
}
155258
}
156259

260+
if ([[eventTags allKeys] containsObject:OPTLYEventMetricNameValue]) {
261+
// Allow only 'value' eventTags with double values; otherwise the value will be cast to a double
262+
NSNumber *numericValue = [self numericValue:config value:eventTags[OPTLYEventMetricNameValue]];
263+
if (numericValue != nil) {
264+
mutableEventTags[OPTLYEventMetricNameValue] = numericValue;
265+
} else {
266+
[mutableEventTags removeObjectForKey:OPTLYEventMetricNameValue];
267+
}
268+
}
269+
157270
NSArray *layerStates = [self createLayerStates:config
158271
bucketer:bucketer
159272
eventKey:eventName
@@ -175,7 +288,7 @@ - (NSDictionary *)buildEventTicket:(OPTLYProjectConfig *)config
175288
params[OPTLYEventParameterKeysEventEntityId] = StringOrEmpty([config getEventIdForKey:eventName]);
176289
params[OPTLYEventParameterKeysEventName] = StringOrEmpty(eventName);
177290
params[OPTLYEventParameterKeysEventFeatures] = [self createEventFeatures:config eventTags:mutableEventTags];
178-
params[OPTLYEventParameterKeysEventMetrics] = [self createEventMetric:config eventTags:mutableEventTags];
291+
params[OPTLYEventParameterKeysEventMetrics] = [self createEventMetrics:config eventTags:mutableEventTags];
179292
params[OPTLYEventParameterKeysLayerStates] = layerStates;
180293

181294
return [params copy];
@@ -191,8 +304,8 @@ - (NSDictionary *)createDecisionWithExperimentId:(NSString *)experimentId
191304
return decisionParams;
192305
}
193306

194-
- (NSArray *)createEventMetric:(OPTLYProjectConfig *)config
195-
eventTags:(NSDictionary *)eventTags
307+
- (NSArray *)createEventMetrics:(OPTLYProjectConfig *)config
308+
eventTags:(NSDictionary *)eventTags
196309
{
197310
NSMutableArray *metrics = [NSMutableArray new];
198311

@@ -202,6 +315,12 @@ - (NSArray *)createEventMetric:(OPTLYProjectConfig *)config
202315
[metrics addObject:metricParam];
203316
}
204317

318+
if ([[eventTags allKeys] containsObject:OPTLYEventMetricNameValue]) {
319+
NSDictionary *metricParam = @{ OPTLYEventParameterKeysMetricName : OPTLYEventMetricNameValue,
320+
OPTLYEventParameterKeysMetricValue : eventTags[OPTLYEventMetricNameValue] };
321+
[metrics addObject:metricParam];
322+
}
323+
205324
return [metrics copy];
206325
}
207326

OptimizelySDKCore/OptimizelySDKCore/OPTLYEventMetric.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@
2525

2626
NS_ASSUME_NONNULL_BEGIN
2727
extern NSString * const OPTLYEventMetricNameRevenue;
28+
extern NSString * const OPTLYEventMetricNameValue;
2829
NS_ASSUME_NONNULL_END
2930

3031
@protocol OPTLYEventMetric
3132
@end
3233

3334
@interface OPTLYEventMetric : OPTLYJSONModel
3435

35-
// The name of the metric, e.g. 'revenue'
36+
// The name of the metric, e.g. 'revenue' or 'value'
3637
@property (nonatomic, strong, nonnull) NSString *name;
3738
// The value of the metric
38-
@property (nonatomic, assign) long value;
39+
@property (nonatomic, strong, nonnull) NSNumber *value;
3940

4041
@end

OptimizelySDKCore/OptimizelySDKCore/OPTLYEventMetric.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#import "OPTLYEventMetric.h"
1818

1919
NSString * const OPTLYEventMetricNameRevenue = @"revenue";
20+
NSString * const OPTLYEventMetricNameValue = @"value";
2021

2122
@implementation OPTLYEventMetric
2223

OptimizelySDKCore/OptimizelySDKCore/OPTLYLoggerMessages.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,17 @@ extern NSString *const OPTLYLoggerMessagesNotBuildingDecisionEventTicket;
101101
extern NSString *const OPTLYLoggerMessagesUserIdInvalid;
102102
extern NSString *const OPTLYLoggerMessagesVariationIdInvalid;
103103
extern NSString *const OPTLYLoggerMessagesEventNotPassAudienceEvaluation;
104-
extern NSString *const OPTLYLoggerMessagesReveneuValueInvalidInteger;
104+
extern NSString *const OPTLYLoggerMessagesRevenueValueFloat;
105105
extern NSString *const OPTLYLoggerMessagesRevenueValueString;
106+
extern NSString *const OPTLYLoggerMessagesRevenueValueIntegerOverflow;
107+
extern NSString *const OPTLYLoggerMessagesRevenueValueFloatOverflow;
108+
extern NSString *const OPTLYLoggerMessagesRevenueValueInvalidBoolean;
106109
extern NSString *const OPTLYLoggerMessagesRevenueValueInvalid;
110+
extern NSString *const OPTLYLoggerMessagesNumericValueString;
111+
extern NSString *const OPTLYLoggerMessagesNumericValueInvalidBoolean;
112+
extern NSString *const OPTLYLoggerMessagesNumericValueInvalidFloat;
113+
extern NSString *const OPTLYLoggerMessagesNumericValueInvalidString;
114+
extern NSString *const OPTLYLoggerMessagesNumericValueInvalid;
107115
extern NSString *const OPTLYLoggerMessagesEventTagValueInvalid;
108116

109117
// ---- Event Dispatcher ----

OptimizelySDKCore/OptimizelySDKCore/OPTLYLoggerMessages.m

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,18 @@
9797
NSString *const OPTLYLoggerMessagesUserIdInvalid = @"[EVENT BUILDER] User ID cannot be an empty string.";
9898
NSString *const OPTLYLoggerMessagesVariationIdInvalid = @"[EVENT BUILDER] Variation ID cannot be an empty string.";
9999
NSString *const OPTLYLoggerMessagesEventNotPassAudienceEvaluation = @"[EVENT BUILDER] None of the experiments of %@ pass audience evaluation.";
100-
NSString *const OPTLYLoggerMessagesReveneuValueInvalidInteger = @"[EVENT BUILDER] Provided revenue value is an invalid integer type and will be cast to the integer: %llu.";
101-
NSString *const OPTLYLoggerMessagesRevenueValueString = @"[EVENT BUILDER] Provided revenue value is a string and will be cast to the integer: %llu.";
100+
NSString *const OPTLYLoggerMessagesRevenueValueFloat = @"[EVENT BUILDER] Provided float revenue value %@ will be cast to integer %@.";
101+
NSString *const OPTLYLoggerMessagesRevenueValueString = @"[EVENT BUILDER] Provided string revenue value will be cast to integer %@.";
102+
NSString *const OPTLYLoggerMessagesRevenueValueIntegerOverflow = @"[EVENT BUILDER] Provided unsigned long long revenue value %@ overflows long long type and will not be sent to results.";
103+
NSString *const OPTLYLoggerMessagesRevenueValueFloatOverflow = @"[EVENT BUILDER] Provided float revenue value %@ overflows long long type and will not be sent to results.";
104+
NSString *const OPTLYLoggerMessagesRevenueValueInvalidBoolean = @"[EVENT BUILDER] Provided revenue value %@ is an invalid boolean type and will not be sent to results.";
102105
NSString *const OPTLYLoggerMessagesRevenueValueInvalid = @"[EVENT BUILDER] Provided revenue value is in an invalid format and will not be sent to results.";
103-
NSString *const OPTLYLoggerMessagesEventTagValueInvalid = @"[EVENT BUILDER] Provided event tag %@ is neither an integer nor a string; skipping.";
104-
106+
NSString *const OPTLYLoggerMessagesNumericValueString = @"[EVENT BUILDER] Provided string numeric value will be cast to float %@.";
107+
NSString *const OPTLYLoggerMessagesNumericValueInvalidBoolean = @"[EVENT BUILDER] Provided numeric value %@ is an invalid boolean type and will not be sent to results.";
108+
NSString *const OPTLYLoggerMessagesNumericValueInvalidFloat = @"[EVENT BUILDER] Provided numeric value %@ is an invalid float type and will not be sent to results.";
109+
NSString *const OPTLYLoggerMessagesNumericValueInvalidString = @"[EVENT BUILDER] Provided numeric value is a string %@ that could not be cast to a valid float.";
110+
NSString *const OPTLYLoggerMessagesNumericValueInvalid = @"[EVENT BUILDER] Provided numeric value is in an invalid format and will not be sent to results.";
111+
NSString *const OPTLYLoggerMessagesEventTagValueInvalid = @"[EVENT BUILDER] Provided event tag %@ is neither an integer nor a string and will not be sent to results.";
105112

106113
// ---- Event Dispatcher ----
107114
// info

0 commit comments

Comments
 (0)