{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-} module AutoInstrument.Internal.Types ( AutoInstrument(..) ) where import qualified Data.Text as T import UnliftIO import qualified OpenTelemetry.Propagator as Otel import qualified OpenTelemetry.Trace.Core as Otel class AutoInstrument a where autoInstrument :: String -- function name -> String -- module name -> String -- file path -> String -- line number -> String -- package name -> a -> a instance {-# INCOHERENT #-} AutoInstrument b => AutoInstrument (a -> b) where autoInstrument funName modName filePath lineNum pkgName f = autoInstrument funName modName filePath lineNum pkgName . f instance MonadUnliftIO m => AutoInstrument (m a) where autoInstrument funName modName filePath lineNum pkgName body = do tp <- Otel.getGlobalTracerProvider -- If the global tracer provider hasn't been initialized then there will -- be no propagators. Don't create a span if this is the case because if -- the function that initializes the tracer provider gets auto instrumented -- then its span will not emit traces and nor will its child spans. if null $ Otel.propagatorNames (Otel.getTracerProviderPropagators tp) then body -- no providers - don't create a span else -- TODO store this in a global var as an optimization? might not want to -- since the global tracer provider can potentially change. let tracer = Otel.makeTracer tp "hs-opentelemetry-instrumentation-auto" Otel.tracerOptions attrs = [ (T.pack "code.function", Otel.toAttribute $ T.pack funName) , (T.pack "code.namespace", Otel.toAttribute $ T.pack modName) , (T.pack "code.filepath", Otel.toAttribute $ T.pack filePath) , (T.pack "code.lineno", Otel.toAttribute $ T.pack lineNum) , (T.pack "code.package", Otel.toAttribute $ T.pack pkgName) ] #if MIN_VERSION_hs_opentelemetry_api(0,1,0) spanArgs = Otel.addAttributesToSpanArguments attrs Otel.defaultSpanArguments in Otel.inSpan tracer (T.pack funName) spanArgs body #else spanArgs = Otel.defaultSpanArguments { Otel.attributes = attrs } in Otel.inSpan'' tracer [] (T.pack funName) spanArgs (const body) #endif