Closed alaendle closed 3 years ago
To make things more clear - the following code (which I hope at least somehow makes sense):
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Monad.Trace (TraceT)
import qualified Control.Monad.Trace.Class as TC
import qualified Monitor.Tracing.Zipkin as ZPK
import Control.Monad.IO.Class (liftIO)
rootService :: TraceT IO ZPK.B3
rootService = TC.rootSpan TC.alwaysSampled "root" $ ZPK.producerSpanWith id "producer" (\(Just b3) -> pure b3)
consumerService :: ZPK.B3 -> TraceT IO ()
consumerService b3 = ZPK.consumerSpanWith id b3 $ liftIO $ print b3
main :: IO ()
main = do
b3 <- ZPK.with ZPK.defaultSettings { ZPK.settingsEndpoint = Just "rootEndpoint" } $ ZPK.run rootService
ZPK.with ZPK.defaultSettings { ZPK.settingsEndpoint = Just "consumerEndpoint" } $ ZPK.run $ consumerService b3
leads to three spans
[
{
"traceId": "38a798d0ca78faf3a027c3e78a2f16dd",
"id": "bef37d00fcf35d42",
"name": "root",
"timestamp": 1616664131719454,
"localEndpoint": {
"serviceName": "rootendpoint"
}
},
{
"traceId": "38a798d0ca78faf3a027c3e78a2f16dd",
"parentId": "bef37d00fcf35d42",
"id": "131cb0bb5ad7e036",
"kind": "PRODUCER",
"name": "producer",
"timestamp": 1616664131719454,
"localEndpoint": {
"serviceName": "rootendpoint"
}
},
{
"traceId": "38a798d0ca78faf3a027c3e78a2f16dd",
"id": "131cb0bb5ad7e036",
"kind": "CONSUMER",
"timestamp": 1616664134461970,
"duration": 977,
"localEndpoint": {
"serviceName": "consumerendpoint"
}
}
]
Please note that the last span, the CONSUMER
span, has no parentId (I'm unsure if this is correct) and that the id
is the same as the id
of the producer (which is a violation of the specification, or isn't it?).
/cc @mtth
Not sure if this is correct, but maybe line 306 in Zipkin.hs
should just be changed to something like
, builderReferences = Set.singleton (ChildOf $ b3SpanID b3)
Hi @alaendle. Thanks for the detailed report and investigation - I think you're right, consumerSpanWith
should create a child span instead. If I read the spec correctly we'd also want to keep serverSpanWith
as-is, so we need to do a bit of refactoring beyond importB3
(for example inlining/specializing it along with incomingSpan
inside serverSpanWith
and consumerSpanWith
). Is this something you would be interested in contributing?
To be honest I'm still a newbie to all the details of span propagation, but what caught my intention was the fact that in this framework PRODUCER/CONSUMER spans act the same way as CLIENT/SERVER spans.
But as far as I understood https://zipkin.io/pages/instrumenting.html ("Message Tracing is different than RPC tracing because the producer and consumer don’t share span IDs."). Unfortunately the specification how things should behave seems to be inexistent - at least I couldn't find a document that describes the correct behaviour.
Please let me know if this is really an issue - my guess is that someone who wrote such a library must be an expert to these topics 😉 Thanks in advance!