Skip to content

Conversation

@rashidsp
Copy link
Contributor

@rashidsp rashidsp commented Jan 8, 2019

Summary

This adds logging to audience evaluation.

Test plan

Unit tests written in

  • spec/audience_spec.rb
  • spec/custom_attribute_condition_evaluator_spec.rb

Issues

  • OASIS-3852
@rashidsp rashidsp requested a review from oakbani January 8, 2019 17:33
@rashidsp rashidsp added the WIP Work in progress label Jan 8, 2019
@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling fabf023 on rashid/logging-for-audience into 37872e6 on rashid/audience-match-types.

1 similar comment
@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling fabf023 on rashid/logging-for-audience into 37872e6 on rashid/audience-match-types.

@coveralls
Copy link

coveralls commented Jan 8, 2019

Coverage Status

Coverage decreased (-0.05%) to 99.945% when pulling 30d9330 on rashid/logging-for-audience into 4c8b534 on master.

Copy link
Contributor

@oakbani oakbani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall.
Missing attribute value Log Level was decided to be changed from WARNING to DEBUG.


if user_provided_value.nil? && condition_match != EXISTS_MATCH_TYPE
@logger.log(
Logger::WARN,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logger::DEBUG?

unless value_valid_for_exact_conditions?(user_provided_value)
@logger.log(
Logger::WARN,
"Audience condition '#{condition}' evaluated as UNKNOWN because the value for user " \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log is being used at multiple places. Can we make this a const? Or move all of the logs into a separate file?

Copy link
Contributor Author

@rashidsp rashidsp Jan 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be done for logger improvement at SDK level.
However i have moved log messages to constants file for now.

@config_body_json = OptimizelySpec::VALID_CONFIG_BODY_JSON
@config_typed_audience_json = JSON.dump(OptimizelySpec::CONFIG_DICT_WITH_TYPED_AUDIENCES)
end
let(:config_body) { OptimizelySpec::VALID_CONFIG_BODY }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit. unused

"Audience '3468206646' evaluated as 'true'."
)

expect(spy_logger).to have_received(:log).once.with(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we assert that these logs have been called in the given sequence? OR assert the total number of calls to ensure nothing else is being logged?

condition = {'match' => 'exact', 'name' => 'weird_condition', 'type' => 'weird', 'value' => 'hi'}
condition_evaluator = Optimizely::CustomAttributeConditionEvaluator.new({'weird_condition' => 'bye'}, spy_logger)
expect(condition_evaluator.evaluate(condition)).to eq(nil)
expect(spy_logger).to have_received(:log).once.with(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit. Can we use a construct that ensures that :log is called once and only with this message?

)
end

it 'should log and return nil if there user-provided value is of a unexpected type' do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit. 'there'

@rashidsp rashidsp changed the base branch from rashid/audience-match-types to master January 9, 2019 11:56
@rashidsp rashidsp self-assigned this Jan 9, 2019
@rashidsp rashidsp removed the WIP Work in progress label Jan 9, 2019
@rashidsp rashidsp requested a review from a team January 9, 2019 12:09
Copy link
Contributor

@nchilada nchilada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Thanks for updating this in line with the other SDKs; I think I only found nits. 👏

Helpers::Validator.finite_number?(condition_value) &&
Helpers::Validator.finite_number?(user_provided_value)

return true if user_provided_value == condition_value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to do some kind of special comparison instead of user_provided_value == condition_value in order to account for cases in which user_provided_value and condition_value are of different numeric types?

If not, I think it'd be cleaner to rely on the equality check that already occurs at the end of this function. At the very least, this would be consistent with most of our other SDKs. In exchange, we'd have to modify Helpers::Validator.same_types? to return true in the case of different numeric types.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. It will be much cleaner that way.

format(Helpers::Constants::AUDIENCE_EVALUATION_LOGS['UNKNOWN_CONDITION_VALUE'], condition)
)
return nil
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: would be slightly better (and certainly more consistent with other SDKs) to reorder the above two blocks. If the condition_value isn't a string, that'd be indicative of a broader problem that might be resolved in a future SDK, where it might actually be legitimate for the user_provided_value to be a non-string.

(I know we check for non-nil user_provided_value before we get to either of these blocks, but at least that helps us increase code re-use...)

user_attributes)).to be false
expect(spy_logger).to have_received(:log).once.with(
Logger::DEBUG,
"Evaluating audiences for experiment 'test_experiment_with_audience': #{experiment['audienceIds']}."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid string interpolation in these tests? It'd be helpful to show what the final strings look like, especially since we're relying on Ruby's string representation of the underlying hash.

Copy link
Contributor

@aliabbasrizvi aliabbasrizvi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@nchilada nchilada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Thanks again!

# false otherwise.
# Numeric values are considered as same type.

return true if value_1.is_a?(Numeric) && value_2.is_a?(Numeric)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it's okay to do the numeric check before the boolean check, in Ruby. I've confirmed that true and false are not Numerics.

@nchilada nchilada merged commit c2a0931 into master Mar 6, 2019
@nchilada nchilada deleted the rashid/logging-for-audience branch March 6, 2019 17:52
return true if value_1.is_a?(Numeric) && value_2.is_a?(Numeric)

return true if boolean?(value_1) && boolean?(value_2)
return true if value_1.is_a?(Integer) && value_2.is_a?(Integer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for changing this! I just did some final QA for the 3.0 release, and I'm sure this would have been a problem if we hadn't changed it. We do expect numbers and floats to be interchangeable for the purposes of audience targeting. 👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

5 participants