mtth / tracing

Distributed tracing
https://hackage.haskell.org/package/tracing
BSD 3-Clause "New" or "Revised" License
24 stars 11 forks source link

How to run instrumented code without span collection? #10

Closed alaendle closed 3 years ago

alaendle commented 3 years ago

If I have instrumented code and want to disable tracing, how do I run that? I have no Zipkin-Endpoint at hand and collectSpanSamples will fill up all my memory.

So I wonder if something more intelligent than the following should be provided by the library to actually have something like a "no-operation-trace-runner".

discardSpanSamples :: MonadUnliftIO m => TraceT m a -> m a
discardSpanSamples actn = do
  tracer <- newTracer
  _ <- liftIO $ forkIO $ fix $ \loop -> do
    _ <- atomically $ readTChan (spanSamples tracer)
    loop
  runTraceT actn tracer
mtth commented 3 years ago

Would a new "black hole" instance for MonadTrace work for your use-case?

newtype DiscardT m a = DiscardT { runDiscardT :: m a }
  deriving (Functor, Applicative, Monad, MonadIO, MonadTrans)

-- MonadReader, ...

instance MonadTrace (DiscardT m) where
  trace _ = id
  activeSpan = Nothing
  addSpanEntry _ _ = pure ()

Identity already has such an instance but I assume it doesn't work for you (because of IO?).

alaendle commented 3 years ago

@mtth Many thanks for the idea ❤️ - this works as expected, but it has the downside (forgive me if this is wrong, I'm still a haskell beginner) that I have to decide on compile time if things are traced (the type decides this). If I have a configuration value which decides if tracing is enabled I need to change the behaviour during runtime. So for now I stick with the published discardSpanSamples function - or can you come up with something just like that?

mtth commented 3 years ago

You're right, I'm not sure there would be an easy way to allow toggling it at runtime with that approach. I'm leaning towards adding a runTraceT variant which accepts Maybe Tracer and discards spans if Nothing is provided:

-- | Maybe trace an action. If the tracer is 'Nothing', no spans will be published.
runTraceT' :: TraceT m a -> Maybe Tracer -> m a

I implemented a first version in https://github.com/mtth/tracing/pull/13. Can you try it out and let me know what you think?

alaendle commented 3 years ago

Hi @mtth, many thanks for this branch. I did a quick tests and it seems to work fine.

However that was no extensive testing in regards of correctness and performance - just a quick test to verify the API and basic functionality (but by looking at the relatively small code changes I wouldn't expect any serious problems with the code).

So this implementation would definitely fulfil my requirements and make my discardSpanSamples implementation obsolete.

If you ask if switch to Maybe Scope in newtype TraceT m a = TraceT { traceTReader :: ReaderT (Maybe Scope) m a } is a good design choice, I have to be honest and admit that I as a beginner couldn't answer that question.

mtth commented 3 years ago

Thanks for confirming. The new runTraceT' API is available in 0.0.7.0, just released.