Skip to content
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

feat(decide): Adding support for decide options and decision reasons. #298

Merged
merged 38 commits into from
Dec 15, 2020

Conversation

yasirfolio3
Copy link
Contributor

@yasirfolio3 yasirfolio3 commented Oct 22, 2020

Summary

A part of multiple PRs for Decide API:

  • added DecideOptions.
  • added DecisionReasons.
  • Refactored interfaces with additional parameter of reasons and options.
  • Fixed unit tests throughout the sdk.

Tests

  • Unit tests added.

Copy link

@jaeopt jaeopt left a comment

Choose a reason for hiding this comment

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

I understand that this PR extends existing interface to support changes for new decide APIs. It looks good in that sense.
Not sure if you plan to add them later, but I do not see collecting log messages into DecisionReasons.


// AddError appends given message to the error list.
func (o *DefaultDecisionReasons) AddError(format string, arguments ...interface{}) {
o.mutex.Lock()
Copy link

Choose a reason for hiding this comment

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

Decision reasons should be managed per decision, so no need for concurrency control.

"github.com/optimizely/go-sdk/pkg/entities"
"github.com/optimizely/go-sdk/pkg/logging"
)

// CompositeFeatureService is the default out-of-the-box feature decision service
type CompositeFeatureService struct {
featureServices []FeatureService
logger logging.OptimizelyLogProducer
logger logging.OptimizelyLogProducer
Copy link

Choose a reason for hiding this comment

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

remove extra spaces

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this indentation fix is on purpose, it should be aligned with the text above.

"github.com/optimizely/go-sdk/pkg/decision/evaluator/matchers"
"github.com/optimizely/go-sdk/pkg/entities"
"github.com/optimizely/go-sdk/pkg/logging"
)

// ItemEvaluator evaluates a condition against the given user's attributes
type ItemEvaluator interface {
Evaluate(interface{}, *entities.TreeParameters) (bool, error)
Evaluate(interface{}, *entities.TreeParameters, decide.OptimizelyDecideOptions, decide.DecisionReasons) (bool, error)
Copy link

Choose a reason for hiding this comment

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

No need for OptimizelyDecideOptions here

@@ -61,7 +61,7 @@ func (c CustomAttributeConditionEvaluator) Evaluate(condition entities.Condition
return false, fmt.Errorf(`invalid Condition matcher "%s"`, condition.Match)
Copy link

Choose a reason for hiding this comment

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

Don't we need this to reasons? Basically, we should add all error/warning/info (and some of debug) log messages into reasons when they're decision-related.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

we can probably put it within the reasons

// We should only be evaluating custom attributes

if condition.Type != customAttributeType {

c.logger.Warning(fmt.Sprintf(logging.UnknownConditionType.String(), condition.StringRepresentation))
return false, fmt.Errorf(`unable to evaluate condition of type "%s"`, condition.Type)
Copy link

Choose a reason for hiding this comment

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

Don't we need add this message to reasons?

Copy link
Contributor Author

Choose a reason for hiding this comment

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


// ToReport returns reasons to be reported.
func (o *DefaultDecisionReasons) ToReport() []string {
o.mutex.RLock()
Copy link

Choose a reason for hiding this comment

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

Same. no need for mutex control here.

Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need mutex here ?

s.mockExperimentService.On("GetDecision", s.testDecisionContext, testUserContext).Return(s.testComputedDecision, nil)
s.options = decide.OptimizelyDecideOptions{}
s.reasons = decide.NewDecisionReasons(s.options)
s.mockExperimentService.On("GetDecision", s.testDecisionContext, testUserContext, s.options, s.reasons).Return(s.testComputedDecision, nil)
}

func (s *PersistingExperimentServiceTestSuite) TestNilUserProfileService() {
Copy link

Choose a reason for hiding this comment

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

Not sure if it's planned to add later, but we need test cases to validate "IgnoreUPS" option here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes these tests are included in the succeeding PR. #299

@optimizely optimizely deleted a comment from jaeopt Nov 9, 2020
@yasirfolio3
Copy link
Contributor Author

I understand that this PR extends existing interface to support changes for new decide APIs. It looks good in that sense.
Not sure if you plan to add them later, but I do not see collecting log messages into DecisionReasons.

yes i was waiting for one of the PR's on other sdk's to finalize so that i can add messages to decision reasons, will do that in another PR.

s.logger.Debug(fmt.Sprintf(logging.ExperimentAudiencesEvaluatedTo.String(), experiment.Key, evalResult))
if !evalResult {
s.logger.Debug(fmt.Sprintf(logging.UserNotInExperiment.String(), userContext.ID, experiment.Key))
experimentDecision.Reason = reasons.FailedAudienceTargeting
experimentDecision.Reason = pkgReasons.FailedAudienceTargeting
Copy link
Contributor Author

@yasirfolio3 yasirfolio3 Nov 10, 2020

Choose a reason for hiding this comment

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

This comment was originally added by @jaeopt but got accidentally deleted:

This message should go into new DecisionReasons as well.
Wondering how we can merge this existing "Reason" with new DecisionReasons.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, these make sense

@msohailhussain msohailhussain marked this pull request as ready for review November 10, 2020 22:34
@msohailhussain msohailhussain requested a review from a team as a code owner November 10, 2020 22:34
Copy link

@jaeopt jaeopt left a comment

Choose a reason for hiding this comment

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

LGTM - I expect all reasons collecting in new PRs

Base automatically changed from yasir/user-context-2 to master December 10, 2020 19:16
Copy link
Contributor

@pawels-optimizely pawels-optimizely left a comment

Choose a reason for hiding this comment

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

reasons are passed to Evaluator, condition and Matchers, but I don't think they are used.
Please either clean them up (remove them) or use them.

ExcludeVariables: true,
}
reasons := NewDecisionReasons(options)
reasons.AddError("error message")
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a test with arguments ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done 👍

@yasirfolio3
Copy link
Contributor Author

reasons are passed to Evaluator, condition and Matchers, but I don't think they are used.
Please either clean them up (remove them) or use them.

We will be using them in a separate PR just dedicated to reasons with all the unit tests. 👍

Copy link
Contributor

@msohailhussain msohailhussain left a comment

Choose a reason for hiding this comment

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

lgtm

@@ -49,6 +49,8 @@ type OptimizelyClient struct {
defaultDecideOptions decide.OptimizelyDecideOptions
}

// Decide API
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove

@jaeopt jaeopt merged commit 273fcd9 into master Dec 15, 2020
@jaeopt jaeopt deleted the yasir/decide-api-2 branch December 15, 2020 20:59
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.

4 participants