open-feature / spec

OpenFeature specification
https://openfeature.dev
Apache License 2.0
588 stars 35 forks source link

feat: context propagation #227

Closed lukas-reining closed 4 months ago

lukas-reining commented 6 months ago

This PR

Adds context propagation as described in #81.

To me it looks like this should be implementable in all the current languages.

The following things I am not sure on:

Related Issues

Fixes #81

toddbaert commented 5 months ago

Hey @lukas-reining - sorry for a slow response from my part on this. I will be reviewing this first thing on Monday.

beeme1mr commented 5 months ago

I wouldn't consider myself a polyglot developer, so I have some concerns about how this could be implemented in languages like Rust and Go. Perhaps we should change RFC-2119 keyword to "SHOULD" or "MAY" to avoid requiring a feature that can't reasonably be implemented in some technologies.

@sheepduke what are your thoughts from Rust perspective?

austindrenski commented 5 months ago

@beeme1mr wrote https://github.com/open-feature/spec/pull/227#issuecomment-1900692701:

[...] I have some concerns about how this could be implemented in languages like [...] Go. [...]

I'm relatively new to Go, but to me this sounds quite comparable to how OTel trace and baggage propagation works, i.e., via the context package.

For example, if I want to start a child trace in Go, I can write:

const scopeName = "github.com/some-repo/some-module"

func someFunc(ctx context.Context) error {
    // create a new child span from the incoming ctx, and overwrite/shadow it with a new ctx
    ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer(scopeName).Start(ctx, "some_func")
    defer span.End()

    // do stuff covered by the child span
    // ...
    // ...

    // now call into someOtherFunc, passing the overwritten/shadowed ctx
    return someOtherFunc(ctx)
}

func someOtherFunc(ctx context.Context) error {
    ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer(scopeName).Start(ctx, "some_other_function")
    defer span.End()

    // do stuff covered by the child (grandchild?) span
    // ...
    // ...

    return nil
}

With the resulting span looking something like:

github.com/some-repo/some-module:some_func       |-----------------------------------------|
github.com/some-repo/some-module:some_other_func               |---------------------------|

or if the caller to someFunc passed a ctx that already contained a span:

some_outer_caller                                |-----------------------------------------|
github.com/some-repo/some-module:some_func                |---------------|
github.com/some-repo/some-module:some_other_func               |----------|

Related

lukas-reining commented 5 months ago

I'm relatively new to Go, but to me this sounds quite comparable to how OTel trace and baggage propagation works, i.e., via the context package.

Yes exactly, this is how it was meant.

lukas-reining commented 5 months ago

Perhaps we should change RFC-2119 keyword to "SHOULD" or "MAY" to avoid requiring a feature that can't reasonably be implemented in some technologies.

I would be fine with this, but my feeling is that there should be a way in all languages. But to be sure we could also just go for SHOULD to prevent the case of a language not capable of implementing it. @beeme1mr

lukas-reining commented 5 months ago

Perhaps we should change RFC-2119 keyword to "SHOULD" or "MAY" to avoid requiring a feature that can't reasonably be implemented in some technologies.

I would be fine with this, but my feeling is that there should be a way in all languages. But to be sure we could also just go for SHOULD to prevent the case of a language not capable of implementing it. @beeme1mr

@beeme1mr If we go for SHOULD, how would we express that if transaction propagation is implemented, then all methods have to be implemented. A new condition feels too much? Or maybe that the right thing here?

beeme1mr commented 5 months ago

I would just add a short blurb in the non-normative section.

toddbaert commented 5 months ago

Perhaps we should change RFC-2119 keyword to "SHOULD" or "MAY" to avoid requiring a feature that can't reasonably be implemented in some technologies. I would be fine with this, but my feeling is that there should be a way in all languages. But to be sure we could also just go for SHOULD to prevent the case of a language not capable of implementing it. @beeme1mr

@beeme1mr If we go for SHOULD, how would we express that if transaction propagation is implemented, then all methods have to be implemented. A new condition feels too much? Or maybe that the right thing here?

I think you could do a single condition and put everything under that if you want, but I also think you could get away without one.

You could use a should/may and then just say "the transaction propagation implementation must..." and I think people would probably interpret that as not applicable.

lukas-reining commented 5 months ago

Perhaps we should change RFC-2119 keyword to "SHOULD" or "MAY" to avoid requiring a feature that can't reasonably be implemented in some technologies. I would be fine with this, but my feeling is that there should be a way in all languages. But to be sure we could also just go for SHOULD to prevent the case of a language not capable of implementing it. @beeme1mr

@beeme1mr If we go for SHOULD, how would we express that if transaction propagation is implemented, then all methods have to be implemented. A new condition feels too much? Or maybe that the right thing here?

I think you could do a single condition and put everything under that if you want, but I also think you could get away without one.

You could use a should/may and then just say "the transaction propagation implementation must..." and I think people would probably interpret that as not applicable.

I chose to add a condition now @toddbaert @beeme1mr. It feels the cleanest to me this way. I also tried to say "the transaction propagation implementation must..." but it felt hard for 3.3.1.2.1 to say this and that the method must be on the API.

The only concern I have is the deep nesting, something like 3.3.1.2.1 feels pretty heavy but it feels better than having conditions or assumptions in the spec sentences. What do you think?

toddbaert commented 5 months ago

The only concern I have is the deep nesting, something like 3.3.1.2.1 feels pretty heavy but it feels better than having conditions or assumptions in the spec sentences. What do you think?

I'm OK with the deep nesting. I hope we never have to go deeper than 5, but I think it's fine.

lukas-reining commented 5 months ago

As said in the community meeting we have enough approvals now and it seems that we have a consensus. We will merge this next Wednesday (08.02) if there is no blocking feedback or any objections until then.