-
-
Notifications
You must be signed in to change notification settings - Fork 37
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
[http-client] using hooks #144
base: main
Are you sure you want to change the base?
Conversation
managerModifyRequest
and managerModifyResponse
to implement this instrumentation…mplement this instrumentation
a192ebe
to
b0bfa6b
Compare
This is ready to be review! |
import qualified OpenTelemetry.Trace.Core as Otel | ||
|
||
|
||
appendModifierToSettings :: (MonadIO m, HasCallStack) => Otel.TracerProvider -> Orig.ManagerSettings -> m Orig.ManagerSettings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haddock?
|
||
|
||
appendModifierToSettings :: (MonadIO m, HasCallStack) => Otel.TracerProvider -> Orig.ManagerSettings -> m Orig.ManagerSettings | ||
appendModifierToSettings tracerProvider settings = withFrozenCallStack $ liftIO $ do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think freezing the call stack helps here?
|
||
requestModifier :: HasCallStack => Otel.Tracer -> ThreadLocalStorage -> Orig.Request -> IO Orig.Request | ||
requestModifier tracer tls request = do | ||
spanRef <- TLS.getTLS tls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, there's some kind of important set of assumptions here about how requests and responses are handled. It looks to me like you're assuming that a response to a request will always be exactly the next response processed by the thread that sent the response. Is that true? It could do with some explanation as to why we think it is true if so!
(That assumption is important because it means we can use a thread-local storage to effectively identify a request: if a response comes back and there is something in the storage, it must be for the request that we sent.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That point is certainly very important. I had made that assumption unconsciously. I will check it out. Maybe I need to think of another way.
case maybeSpan of | ||
Just span_ -> do | ||
Otel.addAttributes span_ $ makeResponseAttributes response | ||
Otel.endSpan span_ Nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if there is no response? or if an exception is thrown? I think this version is less safe in the presence of failures than the old one. The old one used the inSpan
functions, so should never leave us with unterminated spans, but I think this one can do?
makeThreadLocalStorage = TLS.mkTLS $ newIORef Nothing | ||
|
||
|
||
makeRequestAttributes :: Orig.Request -> Otel.AttributeMap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes look useful, though!
What
managerModifyRequest
andmanagerModifyResponse
to implement this instrumentationManager
Why
How
ManagerSetting
provides hooks for requests and responsescreateSpan
in a hook for a request and to callendSpan
in a hook for a responseThreadLocalStorage
is used to transport span data created in a hook for a request to a hook for a responseNote
Cachix @sandydoo seems to implement a similar instrumentation.
https://github.com/cachix/hs-opentelemetry-instrumentation-http-client/