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

Replace SpanBuilder#wrapResource API #273

Merged
merged 3 commits into from
Jul 24, 2023

Conversation

NthPortal
Copy link
Contributor

@NthPortal NthPortal commented Jul 7, 2023

Replace SpanBuilder#wrapResource with
SpanOps#resource:Resource[F,F~>F], which no longer automatically
provides 'acquire', 'use' and 'release' spans.

This API change allows further simplification of the API in future commits.

This PR is a follow-up to the discussion on #261.

  • rebase -i --autosquash before merge

@NthPortal
Copy link
Contributor Author

cc: @iRevive @rossabaker @armanbilge

@NthPortal
Copy link
Contributor Author

NthPortal commented Jul 7, 2023

there is an argument that the entirety of SpanOps can now be discarded, with the new SpanOps#resource method moving to SpanBuilder and replacing build (name can be bikeshedded)

@NthPortal NthPortal force-pushed the Tracer-spanResource/PR branch 2 times, most recently from ec21382 to e8b6044 Compare July 7, 2023 16:28
@NthPortal
Copy link
Contributor Author

Looking at this some more, the only way to directly access the Span anymore is startUnmanaged. is that still needed? should it be moved? should SpanOps be kept just for that and resource?

@iRevive
Copy link
Contributor

iRevive commented Jul 7, 2023

I'm firmly against removing SpanOps. SpanOps provides the only option to modify the span somewhere downstream.

For example, I can do the following:

tracer.span("my-span").use { span =>
  for {
    isSuccess <- someLogic
    _ <- span.addAttribute(Attribute("success", isSuccess))
  } yield ()
}

With F ~> F we cannot do such a thing.

@iRevive
Copy link
Contributor

iRevive commented Jul 7, 2023

I like the direction. The moment we limited tracing to Local semantics, wrapResource does not offer much benefit.

If someone needs it, a similar tracing (acquire, use, release) can be achieved with a few lines utility method.

@NthPortal
Copy link
Contributor Author

NthPortal commented Jul 7, 2023

pushed a commit where resource now returns Resource[F, (Span[F], F ~> F)].

If someone needs it, a similar tracing (acquire, use, release) can be achieved with a few lines utility method.

TracerSuite currently defines such a method, so that I didn't have to mess with the test outputs.

I think I agree that it's still worth keeping SpanOps even with this change, however, as it allows a user to not have to faff about with the natural transformation. however, we can probably make the other methods final defs that delegate to resource (other than startUnmanaged).

edit: they cannot be final defs as things are because they require MonadCancelThrow. unless we're okay with requiring MonadCancelThrow as an implicit parameter for those? I definitely am

Comment on lines 136 to 150
.spanResource("Start up")
.use { case (_, nt /* natural transformation */ ) =>
for {
_ <- nt(tracer.span("acquire").surround(IO.sleep(50.millis)))
_ <- nt {
tracer.span("use").surround {
userIdAlg
.getAllUsersForInstitution(
"9902181e-1d8d-4e00-913d-51532b493f1b"
)
.flatMap(IO.println)
}
}
_ <- nt(tracer.span("release").surround(IO.sleep(100.millis)))
} yield ()
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm concerned that my original commit implemented this incorrectly (before I'd quite understood things), but nothing caught it. is there a way we can run the examples and make sure they're correct?

Copy link
Member

Choose a reason for hiding this comment

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

Hmm. sbt-doctest can make unit tests out of scaladoc comments, but I don't know of anything that tests the output of examples.

@NthPortal
Copy link
Contributor Author

I've pretty much done the simplification (you can see it at https://github.com/NthPortal/otel4s/tree/Tracer-simplify/R1), but I'm holding off on PRing it until everything is hashed out in this PR

@rossabaker
Copy link
Member

I'm firmly against removing SpanOps. SpanOps provides the only option to modify the span somewhere downstream.

In Natchez, there's a near 1:1 relationship between things you can do on a span and things you can do on a Tracer without a reference to the Span. To check my understanding, is that the basic tradeoff we've made here: we have to carry around a SpanOps but not mirror all the span operations?

Copy link
Member

@rossabaker rossabaker left a comment

Choose a reason for hiding this comment

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

Nice work!

Comment on lines 136 to 150
.spanResource("Start up")
.use { case (_, nt /* natural transformation */ ) =>
for {
_ <- nt(tracer.span("acquire").surround(IO.sleep(50.millis)))
_ <- nt {
tracer.span("use").surround {
userIdAlg
.getAllUsersForInstitution(
"9902181e-1d8d-4e00-913d-51532b493f1b"
)
.flatMap(IO.println)
}
}
_ <- nt(tracer.span("release").surround(IO.sleep(100.millis)))
} yield ()
}
Copy link
Member

Choose a reason for hiding this comment

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

Hmm. sbt-doctest can make unit tests out of scaladoc comments, but I don't know of anything that tests the output of examples.

examples/src/main/scala/TraceExample.scala Outdated Show resolved Hide resolved
examples/src/main/scala/TraceExample.scala Outdated Show resolved Hide resolved
@iRevive
Copy link
Contributor

iRevive commented Jul 8, 2023

In Natchez, there's a near 1:1 relationship between things you can do on a span and things you can do on a Tracer without a reference to the Span. To check my understanding, is that the basic tradeoff we've made here: we have to carry around a SpanOps but not mirror all the span operations?

Hm, it's a nice question. We can keep some conversation here #89, to make things easier

Copy link
Contributor

@iRevive iRevive left a comment

Choose a reason for hiding this comment

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

I like the current changes, thanks for the contribution!

There are a few leftovers (e.g. remove Result type member, etc) I can take care of.

@NthPortal
Copy link
Contributor Author

There are a few leftovers (e.g. remove Result type member, etc) I can take care of.

too late ;)

Copy link
Contributor

@iRevive iRevive left a comment

Choose a reason for hiding this comment

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

Looks good. Only one change is up for discussion.

examples/src/main/scala/TracingExample.scala Outdated Show resolved Hide resolved
@NthPortal NthPortal requested a review from iRevive July 17, 2023 17:08
@@ -105,9 +136,3 @@ trait SpanOps[F[_]] {
*/
def surround[A](fa: F[A]): F[A]
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 can still be final ... = use(_ => fa), will change momentarily

Copy link
Member

Choose a reason for hiding this comment

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

It's not final on Resource itself. I wonder whether that implies possible optimizations. But I can't imagine any offhand.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

technically you can optimise the no-op implementation slightly by not creating a wrapper Function1 around the F[A] to pass to use, but honestly I still feel it's cleaner to have it be final. it can be made not final in a minor release if minds are changed later. or someone can make a PR after this is merged. or if others also want it non-final, I can add another fixup commit to this PR

@NthPortal
Copy link
Contributor Author

if no one else has any objections within a couple days, I'll autosquash so this can be ready to merge

Copy link
Member

@rossabaker rossabaker left a comment

Choose a reason for hiding this comment

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

This is tremendous, both the code and review discussion. I should take vacations more often!

Replace `SpanBuilder#wrapResource` with
`SpanOps#resource:Resource[F,F~>F]`, which no longer automatically
provides 'acquire', 'use' and 'release' spans.

This API change allows further simplification of the API in future
commits.
Add `SpanOps.Res` type for the return type of `SpanOps#resource`,
for clearer, more evolvable and more documentable API.
@iRevive iRevive merged commit 5a90aac into typelevel:main Jul 24, 2023
@iRevive
Copy link
Contributor

iRevive commented Jul 24, 2023

Thanks for the contribution @NthPortal!

@NthPortal NthPortal deleted the Tracer-spanResource/PR branch July 24, 2023 15:38
@NthPortal
Copy link
Contributor Author

NthPortal commented Jul 24, 2023

@iRevive thank you for reviewing this PR and collaborating with me!

@NthPortal NthPortal mentioned this pull request Jul 24, 2023
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.

3 participants