-
Notifications
You must be signed in to change notification settings - Fork 63
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
Improvements to fractional custom evalutor #843
Comments
👋 @toddbaert. I took a quick look at this. The first step is easy. For part 2, flag key also used as input to hash, one way I imagine this could be accomplished is by adding the flag key to the context/data when calling the functional evaluator. Is that what you were thinking too? Happy to make a PR for this if so. I didn't understand what step 3 is asking: "ability to use nested props as key (user.email)". |
Hey @craigpastro ! If you look at the fractional evaluation doc, the first argument is the property we use for the deterministic bucketing (in addition to the key, which we will add, as you mention). The problem is, it seems to me this property MUST be a top level property in the map. It would be great if we could express the desire to use a nested property, something like However, if this proves too difficult, I'm fine with opening a new issue for that feature, or just avoiding it. The more important things for the time being are using a different (more popular) hash algo, and also involving the key in the bucketing. |
Thanks for your comment, @toddbaert ! I'll create a draft PR for the first two and read a bit more about I am still wondering how to approach two though. At this point I only have access to the targeting body and the context body. No flag key. Here I go have access to the flag key and can add it to the targeting bytes or the context, so that we can access it in in here, but I am not sure that that is the right approach. WDYT? |
I think the way the JSON logic API works, the best approach might be to pass a new "higher level" map to the JSON logic's apply function, which would contain 2 top level properties: a flag key, and the context. This will avoid us having to add our own flag key prop to the context, which otherwise might trample over a user-added value. I think @bacherfl was playing around with this problem as well, so he might have some ideas. |
Ah, yeah, that is a better idea. I am not sure how this can work with jsonlogic though as it is pushing the data down a level so that vars will also need to account for that? In any case, I'll make a PR for the first part 😄 |
Ya thinking about this more, I'm not sure what I suggested before is feasible. Maybe we could inject the key into the targeting bytes. We do something similar at a different point to allow reuse of shared rules. I'll look into it a bit tomorrow. If we can't make that work nicely, perhaps we can just create some namespacing convention for properties we inject to the context, and document that, to reduce the risk of overwriting stuff from clients. In addition to the flag key, values like the current utc time, etc could be useful, so we should come up with some solution for this. |
The more I think about it, the more I think that adding some attributes directly into the context under some well-defined name is a good idea. Flag key would be one example, but also potentially:
I see these as out-of-scope for this issue, but potentially valuable. I think the thing we need to decide is how to store them. I think perhaps we could put them under a property, perhaps called Once we decide, we can implement the first of these for the |
I was playing around with this last night and it seems to work fine. I think you are right, namespacing and documenting would certainly help. That the risk remains is a bit of a bummer though. There should be a nicer way, but I just don't see it. Recently it seems that a lot of projects are using https://github.com/google/cel-spec for user input custom logic. Maybe this is also something to take a look at? I am not too familiar with it, but have just seen it quite a bit. I can throw together a draft PR using |
Yes, I'd be interested in that. A number of contributors are away because there was some holidays this week in EU, but if you open a draft I'm sure people will comment over the next week. |
I like the idea of reserving a namespace like |
<!-- Please use this template for your pull request. --> <!-- Please use the sections that you need and delete other sections --> ## This PR <!-- add the description of the PR here --> Replace xxh3 with murmur3 in fractional evaluation's bucketing algorithm. ### Related Issues <!-- add here the GitHub issue that this PR resolves if applicable --> Part 1 of #843. ### Notes <!-- any additional notes for this PR --> ### Follow-up Tasks <!-- anything that is related to this PR but not done here should be noted under this section --> <!-- if there is a need for a new issue, please link it here --> ### How to test <!-- if applicable, add testing instructions under this section --> --------- Signed-off-by: Craig Pastro <pastro.craig@gmail.com> Signed-off-by: Todd Baert <todd.baert@dynatrace.com> Co-authored-by: Todd Baert <todd.baert@dynatrace.com> Co-authored-by: Giovanni Liva <giovanni.liva@dynatrace.com> Co-authored-by: Todd Baert <toddbaert@gmail.com>
I've updated the issue description with our progress so far (thanks again @craigpastro and @bacherfl ) and refined the remaining task. |
Shouldn't 2 and 3 be:
|
Yes, sorry about that! |
<!-- Please use this template for your pull request. --> <!-- Please use the sections that you need and delete other sections --> ## This PR <!-- add the description of the PR here --> This PR adds the flag key as input to the hash in fractional evaluation. Since the evaluation function only has access to user-supplied logic and context, which almost certainly will not contain the flag key, in order to get this data to the evaluation function I add a `flagdProperties` struct to the context via a namespaced key `$flagd`. The `flagdProperties` struct contains the flag key, which is then used as input to the hash. ### Related Issues <!-- add here the GitHub issue that this PR resolves if applicable --> Part 2 of #843. ### Notes <!-- any additional notes for this PR --> ### Follow-up Tasks <!-- anything that is related to this PR but not done here should be noted under this section --> <!-- if there is a need for a new issue, please link it here --> ### How to test <!-- if applicable, add testing instructions under this section --> --------- Signed-off-by: Craig Pastro <pastro.craig@gmail.com> Signed-off-by: Todd Baert <todd.baert@dynatrace.com> Co-authored-by: Todd Baert <toddbaert@gmail.com> Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
@craigpastro do you mind if I take on part 3? I have some time to do it... though I'm more than happy to let you do it if you'd like to (or you've already started). |
Hi @toddbaert. Sorry, I was out most of last week. I do have time to look at it today. I am not sure I completely understand it, but I can give it a shot. |
@bacherfl has fully specified the desired behavior of the evaluator here (important because it will be implemented elsewhere as well). The implementation you've worked on here is quite close already. The main difference is that we want to try to use a JSON-logic expression to extract the bucketing value. See some background discussion here. |
<!-- Please use this template for your pull request. --> <!-- Please use the sections that you need and delete other sections --> ## This PR <!-- add the description of the PR here --> This PR adds the ability to use nested properties for the bucket key in fractional evaluation. It is a breaking change from the current behaviour. If the bucket key is not provided it will default to `{"cat": [{"var":"$flagd.flagKey"}, {"var":"targetingKey"}]}`. @toddbaert I am not sure that my approach to the missing bucket key is the best. I would have preferred to add `{"cat": [{"var":"$flagd.flagKey"}, {"var":"targetingKey"}]}` to the targeting object and let JsonLogic handle it, but it would be a bit clumsy and involve string manipulation. I don't think there is a nice way to do it, but I'll play around a bit more. ### Related Issues <!-- add here the GitHub issue that this PR resolves if applicable --> See #848. Closes #843. ### Notes <!-- any additional notes for this PR --> ### Follow-up Tasks <!-- anything that is related to this PR but not done here should be noted under this section --> <!-- if there is a need for a new issue, please link it here --> ### How to test <!-- if applicable, add testing instructions under this section --> --------- Signed-off-by: Craig Pastro <pastro.craig@gmail.com> Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
The fractional evaluation currently uses xxh3 algo as part of it's bucketing algorithm (see here). In order to support in-memory implementations in other languages, we should use a more popular algorithm, such as
murmur3
(this is popular with other feature flag SDKs as well). Additionally, the algorithm doesn't currently take into account the flag key. This means that, for different flags, bucketing will have a predictable ordinality. The algo should be updated to use both the selected context property AND the flag key as factors to the hash. We also should update the evaluator to be able to use nested context props (not just top level props).Definition of done:
{"var":"some.nested.prop"}
){"cat": [{"var":"$flagd.flagKey"}, {"var":"targetingKey"}]}
(basically what we have now, but expressed as a JSON logic expression)The text was updated successfully, but these errors were encountered: