<div dir="ltr"><div>Thank you for this great discussion!<br></div><div dir="ltr"><br></div><div dir="ltr">> If you consider an execution of a program as a downwards-growing stack, a scoped value is bound to some value at one point in the stack, and the bound value is visible to all frames below that point. That is all: there's no need to consider scopes opening and closing.</div><div dir="ltr"><br></div><div>In theory that's true. But if we take into consideration frameworks like Brave [1], Micrometer [2], OpenTelemetry [3] , Apache Camel [4], Apache Skywalking [5] etc. (so those that work with distributed tracing) that theoretical viewpoint does not hold. It would be a gigantic shame if they would need to always rely on ThreadLocals instead of being able to use the ScopedValues mechanism.<br></div><div><br></div><div>>
It's true that this decision makes scoped values less versatile than thread-local variables, but on the other hand the hard guarantees it provides make programs easier to reason about. On balance, we consider the latter more important than the former. <br></div><div><br></div><div>I completely agree with that however for library instrumentors this separation is extremely important. Also that would cancel out all libraries that want to use scoped values and work in an SPI model where users can add functionalities in an isolated fashion (separate before and after logic). It would require all of the frameworks that I mentioned to completely rewrite their internals so that the user's code execution would be wrapped in a e.g. `ScopedValue.runWhere`.</div><div><br></div><div>> We did consider (and even implement) an API with open() and close() methods, but we discarded it in order to make the use you describe impossible</div><div><br></div><div>I understand that with great power comes great responsibility and you want to guard users from cases like "opening and not closing". I fully understand that because I've been working in the domain of distributed tracing for a decade now and I've seen that particular scenario happen every now and then. It's not a common situation though. Since you've already implemented it once then you did see reasons for doing that. Is there a chance to come back to that discussion? What would need to happen to reopen that conversation once again?</div><div><br></div><div>[1] <a href="https://github.com/openzipkin/brave/blob/6.0.3/brave/src/main/java/brave/Tracer.java#L576-L594">https://github.com/openzipkin/brave/blob/6.0.3/brave/src/main/java/brave/Tracer.java#L576-L594</a></div><div>[2] <a href="https://github.com/micrometer-metrics/micrometer/blob/v1.13.0/micrometer-observation/src/main/java/io/micrometer/observation/Observation.java#L838-L904">https://github.com/micrometer-metrics/micrometer/blob/v1.13.0/micrometer-observation/src/main/java/io/micrometer/observation/Observation.java#L838-L904</a></div><div>[3] <a href="https://github.com/open-telemetry/opentelemetry-java/blob/v1.38.0/context/src/main/java/io/opentelemetry/context/Context.java#L200-L203">https://github.com/open-telemetry/opentelemetry-java/blob/v1.38.0/context/src/main/java/io/opentelemetry/context/Context.java#L200-L203</a></div><div>[4] <a href="https://github.com/apache/camel/blob/camel-4.6.0/components/camel-tracing/src/main/java/org/apache/camel/tracing/ActiveSpanManager.java#L136-L144">https://github.com/apache/camel/blob/camel-4.6.0/components/camel-tracing/src/main/java/org/apache/camel/tracing/ActiveSpanManager.java#L136-L144</a></div><div>[5] <a href="https://skywalking.apache.org/docs/skywalking-java/next/en/setup/service-agent/java-agent/application-toolkit-tracer/">https://skywalking.apache.org/docs/skywalking-java/next/en/setup/service-agent/java-agent/application-toolkit-tracer/</a> (AFAIR upon creation Span is made current and needs to be then closed)<br></div><div dir="ltr"><br><div><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>Pozdrawiam / Best regards,</div><div>Marcin Grzejszczak</div><div><br><div><a href="https://marcin.grzejszczak.pl" target="_blank">https://marcin.grzejszczak.pl</a></div><div><a href="https://toomuchcoding.com" target="_blank">https://toomuchcoding.com</a></div></div></div></div></div></div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">czw., 6 cze 2024 o 10:48 Andrew Haley <<a href="mailto:aph-open@littlepinkcloud.com">aph-open@littlepinkcloud.com</a>> napisał(a):<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 6/5/24 22:31, Marcin Grzejszczak wrote:<br>
<br>
> I am wondering what if I don't want to use a ThreadLocal but<br>
> ScopeValue? Is it the tool to solve this problem? Current API allows<br>
> me to run a lambda within a scope through<br>
> `ScopedValue.runWhere(scopedValue, "foo", () -> {})`. But what if I<br>
> wanted to separate this into 2 steps, the scope opening and closing?<br>
<br>
The structured nature of a scoped value is a part of its essential<br>
design. It is the main difference between scoped values and<br>
thread-local variables.<br>
<br>
If you consider an execution of a program as a downwards-growing<br>
stack, a scoped value is bound to some value at one point in the<br>
stack, and the bound value is visible to all frames below that point.<br>
That is all: there's no need to consider scopes opening and closing.<br>
<br>
It's true that this decision makes scoped values less versatile than<br>
thread-local variables, but on the other hand the hard guarantees it<br>
provides make programs easier to reason about. On balance, we consider<br>
the latter more important than the former.<br>
<br>
We did consider (and even implement) an API with open() and close()<br>
methods, but we discarded it in order to make the use you describe<br>
impossible.<br>
<br>
-- <br>
Andrew Haley (he/him)<br>
Java Platform Lead Engineer<br>
Red Hat UK Ltd. <<a href="https://www.redhat.com" rel="noreferrer" target="_blank">https://www.redhat.com</a>><br>
<a href="https://keybase.io/andrewhaley" rel="noreferrer" target="_blank">https://keybase.io/andrewhaley</a><br>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671<br>
<br>
</blockquote></div></div><div id="DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2"><br><table style="border-top:1px solid #d3d4de"><tr><td style="width:55px;padding-top:13px"><a href="http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail" target="_blank"><img src="https://s-install.avcdn.net/ipm/preview/icons/icon-envelope-tick-green-avg-v1.png" alt="" width="46" height="29" style="width: 46px; height: 29px;"></a></td><td style="width:470px;padding-top:12px;color:#41424e;font-size:13px;font-family:Arial,Helvetica,sans-serif;line-height:18px">Nie zawiera wirusów.<a href="http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail" target="_blank" style="color:#4453ea">www.avg.com</a></td></tr></table><a href="#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2" width="1" height="1"></a></div>