Skip to content

fix(nullfilter): filters out attributes with null values #214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 19, 2018

Conversation

mnoman09
Copy link
Contributor

This will ignore attributes with null values on creation of impression or conversion event.

@coveralls
Copy link

coveralls commented Sep 11, 2018

Pull Request Test Coverage Report for Build 635

  • 6 of 6 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.02%) to 88.997%

Totals Coverage Status
Change from base Build 606: 0.02%
Covered Lines: 2386
Relevant Lines: 2681

💛 - Coveralls

@@ -168,6 +168,11 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig,
List<Attribute> attributesList = new ArrayList<Attribute>();

for (Map.Entry<String, ?> entry : attributes.entrySet()) {
//Ignore null value attribute
if (entry.getValue() == null) {
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 whitelist strings, numbers (probably just ints and doubles for now, but the team might need to discuss more), and booleans rather than blacklisting some of the values we don't want to send? I should mention that OASIS-3537 has been updated and might not have mentioned that initially. 😬

Copy link
Contributor

Choose a reason for hiding this comment

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

@nchilada this is related to OASIS-3535 not for OASIS-3537

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, interesting. @mikeng13 can you clarify the difference between 3535 and 3537?

Copy link
Contributor

Choose a reason for hiding this comment

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

As per my understanding, this is only related to NULL values, while OASIS-3537 is more related to filtering out all unsupported values but we have hold-off for OASIS-3537.

Copy link
Contributor

@mikeproeng37 mikeproeng37 Sep 11, 2018

Choose a reason for hiding this comment

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

I've deprecated 3537 in favor of 3535. So the requirement from @nchilada for this particular PR is right. We should filter out values that aren't strings, numbers, or booleans. This includes filtering out NULLs as well.

@@ -168,6 +168,15 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig,
List<Attribute> attributesList = new ArrayList<Attribute>();

for (Map.Entry<String, ?> entry : attributes.entrySet()) {
//Ignore null value attribute
Copy link
Contributor

Choose a reason for hiding this comment

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

Slightly out of date. Maybe change to

// Filter down to the types of values we're allowed to track.
// Don't allow Longs, BigIntegers, or BigDecimals - they /can/ theoretically be serialized as JSON numbers 
// but may take on values that can't be faithfully parsed by the backend.
// https://github.com/optimizely/avro-schemas/blob/baeba19a7bd227aae67026474aec239110c5801d/event_batch/src/main/avro/EventBatch.avsc#L22

?

@mikecdavis @thomaszurkan-optimizely @mikeng13 @ceimaj can you review what I'm proposing as the supported data types?

@@ -168,6 +168,15 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig,
List<Attribute> attributesList = new ArrayList<Attribute>();

for (Map.Entry<String, ?> entry : attributes.entrySet()) {
//Ignore null value attribute
if (entry.getValue() == null ||
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically this check isn't necessary since null instanceof ... evaluates to false, but it's nice to be explicit in the reference SDK since we may be porting to languages that behave differently. Good thinking!

assertNotSame(feature.getValue(), null);
}
}

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 include explicit unit tests to make sure

  • Integers and Decimals are both tracked. I'm not sure if we can test them distinctly via the compatibility suite, since attribute values have to be serialized via JSON.
  • Longs, BigIntegers, and BigDecimals aren't tracked? We definitely can't test these via the compatibility suite.

Maybe test that Booleans are also trackable (in addition to Strings, which I assume are already tested) but I'm less concerned since those can theoretically be covered by the compatibility suite.

(!(entry.getValue() instanceof String) &&
!(entry.getValue() instanceof Integer) &&
!(entry.getValue() instanceof Double) &&
!(entry.getValue() instanceof Boolean))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a suggestion, Usually don't like too many Not conditions. so why we can't convert it into one not.
!(e.getValue() instanceof String || e.getValue() instanceOf Int .... ) should be equal to the above condition.
@nchilada what do u suggest?

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems reasonable to me!

…ting passed in event factory building list

* Added Unit test to verify bigdecimal and bigInteger are not getting passed in event factory building list
assertNotSame(feature.getValue(), null);
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we test attribute selection for conversion events too?

BTW I think we could combine createImpressionEventIgnoresInvalidAttributes, createImpressionEventWithIntegerDecimalBoolAndStringAttributes , createImpressionEventIgnoresNullAttributes - that'd reduce complexity while also confirming that we merely ignore invalid attributes rather than dropping all attributes when one or two are invalid.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lets leave these Unit Tests. I added one more unit test which is making ConversionEvent and in that unit test we are passing valid and invalid attributes in same attributes map, we are verifying that only valid attributes are getting passed and others are getting ignored. I think that will cover the condition you are asking to verify. So is that ok?

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, that works too. Thanks!

@@ -168,6 +168,16 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig,
List<Attribute> attributesList = new ArrayList<Attribute>();

for (Map.Entry<String, ?> entry : attributes.entrySet()) {
// Filters down to the types of values that are allowed.
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 link to https://github.com/optimizely/avro-schemas/blob/baeba19a7bd227aae67026474aec239110c5801d/event_batch/src/main/avro/EventBatch.avsc#L22 since that's the source of truth? Or actually https://developers.optimizely.com/x/events/api/#Attribute_ might be preferable since not everyone can view the avro-schemas repo

* Added Unit Test To test with ConversionEvent and verified that valid attributes are getting passed and invalid are getting ignored
// Filter down to the types of values we're allowed to track.
// Don't allow Longs, BigIntegers, or BigDecimals - they /can/ theoretically be serialized as JSON numbers
// but may take on values that can't be faithfully parsed by the backend.
// https://github.com/optimizely/avro-schemas/blob/baeba19a7bd227aae67026474aec239110c5801d/event_batch/src/main/avro/EventBatch.avsc#L22
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a private repo. Please don't mention it here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, fair enough. Can we link to https://developers.optimizely.com/x/events/api/#Attribute_ instead?

@mikeproeng37
Copy link
Contributor

FYI, I ran integration tests for these changes and they passed =)

@mikeproeng37 mikeproeng37 merged commit 1bb574a into master Sep 19, 2018
@mikeproeng37 mikeproeng37 deleted the mnoman/removeNullAttrFromPayload branch September 21, 2018 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants