packages feed

hs-opentelemetry-instrumentation-conduit 0.1.0.2 → 1.0.0.0

raw patch · 6 files changed

+141/−15 lines, 6 filesdep +hs-opentelemetry-exporter-in-memorydep +hs-opentelemetry-instrumentation-conduitdep +hs-opentelemetry-sdkdep ~hs-opentelemetry-apiPVP ok

version bump matches the API change (PVP)

Dependencies added: hs-opentelemetry-exporter-in-memory, hs-opentelemetry-instrumentation-conduit, hs-opentelemetry-sdk, hs-opentelemetry-semantic-conventions, hspec, resourcet, vector

Dependency ranges changed: hs-opentelemetry-api

API changes (from Hackage documentation)

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Changelog for hs-opentelemetry-instrumentation-conduit +## 1.0.0.0 - 2026-05-29++- Promoted to 1.0.0.0 for the hs-opentelemetry 1.0 release.+ ## 0.1.0.2  - Relax `hs-opentelemetry-api` bounds to support 0.3.x
LICENSE view
@@ -1,4 +1,4 @@-Copyright Ian Duncan (c) 2021+Copyright Ian Duncan (c) 2021-2026  All rights reserved. 
README.md view
@@ -1,1 +1,3 @@ # hs-opentelemetry-instrumentation-conduit++[![hs-opentelemetry-instrumentation-conduit](https://img.shields.io/hackage/v/hs-opentelemetry-instrumentation-conduit?style=flat-square&logo=haskell&label=hs-opentelemetry-instrumentation-conduit&labelColor=5D4F85)](https://hackage.haskell.org/package/hs-opentelemetry-instrumentation-conduit)
hs-opentelemetry-instrumentation-conduit.cabal view
@@ -1,20 +1,22 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.37.0.+-- This file has been generated from package.yaml by hpack version 0.38.3. -- -- see: https://github.com/sol/hpack -name:               hs-opentelemetry-instrumentation-conduit-version:            0.1.0.2-description:        Please see the README on GitHub at <https://github.com/iand675/hs-opentelemetry/tree/main/instrumentation/conduit#readme>-homepage:           https://github.com/iand675/hs-opentelemetry#readme-bug-reports:        https://github.com/iand675/hs-opentelemetry/issues-author:             Ian Duncan, Jade Lovelace-maintainer:         ian@iankduncan.com-copyright:          2024 Ian Duncan, Mercury Technologies-license:            BSD3-license-file:       LICENSE-build-type:         Simple+name:           hs-opentelemetry-instrumentation-conduit+version:        1.0.0.0+synopsis:       OpenTelemetry instrumentation for Conduit streaming pipelines+description:    Please see the README on GitHub at <https://github.com/iand675/hs-opentelemetry/tree/main/instrumentation/conduit#readme>+category:       OpenTelemetry, Conduit, Streaming+homepage:       https://github.com/iand675/hs-opentelemetry#readme+bug-reports:    https://github.com/iand675/hs-opentelemetry/issues+author:         Ian Duncan, Jade Lovelace+maintainer:     ian@iankduncan.com+copyright:      2024 Ian Duncan, Mercury Technologies+license:        BSD3+license-file:   LICENSE+build-type:     Simple extra-source-files:     README.md     ChangeLog.md@@ -34,6 +36,28 @@   build-depends:       base >=4.7 && <5     , conduit-    , hs-opentelemetry-api ==0.3.*+    , hs-opentelemetry-api ==1.0.*+    , hs-opentelemetry-semantic-conventions >=1.40 && <2     , text+  default-language: Haskell2010++test-suite hs-opentelemetry-instrumentation-conduit-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_hs_opentelemetry_instrumentation_conduit+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , conduit+    , hs-opentelemetry-api ==1.0.*+    , hs-opentelemetry-exporter-in-memory ==1.0.*+    , hs-opentelemetry-instrumentation-conduit ==1.0.*+    , hs-opentelemetry-sdk ==1.0.*+    , hspec+    , resourcet+    , text+    , vector   default-language: Haskell2010
src/OpenTelemetry/Instrumentation/Conduit.hs view
@@ -1,13 +1,44 @@ {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} +{- |+Module      : OpenTelemetry.Instrumentation.Conduit+Copyright   : (c) Ian Duncan, 2021-2026+License     : BSD-3+Description : Trace conduit pipeline stages as spans+Stability   : experimental++= Overview++Wraps individual conduit pipeline stages in trace spans so you can see+how time is spent across your streaming pipeline. Use 'inSpan' to run a+sub-pipeline under a span; exceptions are recorded on the span and rethrown.++= Quick example++@+import Conduit+import Data.ByteString (ByteString)+import OpenTelemetry.Instrumentation.Conduit (inSpan)+import OpenTelemetry.Trace.Core (defaultSpanArguments)++myPipeline :: Tracer -> ConduitT ByteString Void IO ()+myPipeline tracer =+  sourceFile "input.csv"+    .| inSpan tracer "parse" defaultSpanArguments (\_ -> mapC parseRow)+    .| inSpan tracer "transform" defaultSpanArguments (\_ -> mapC transformRow)+    .| sinkFile "output.json"+@+-} module OpenTelemetry.Instrumentation.Conduit where  import Conduit import Control.Exception (SomeException, throwIO) import Data.Text (Text) import GHC.Stack (HasCallStack)+import OpenTelemetry.Attributes.Key (unkey) import OpenTelemetry.Context.ThreadLocal+import qualified OpenTelemetry.SemanticConventions as SC import OpenTelemetry.Trace.Core hiding (getTracer)  @@ -26,5 +57,5 @@     $ \span_ -> do       catchC (f span_) $ \e -> do         liftIO $ do-          recordException span_ [("exception.escaped", toAttribute True)] Nothing (e :: SomeException)+          recordException span_ [(unkey SC.exception_escaped, toAttribute True)] Nothing (e :: SomeException)           throwIO e
+ test/Spec.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Main where++import Conduit+import Control.Exception (SomeException, throwIO, try)+import Control.Monad.IO.Class (liftIO)+import Data.IORef+import qualified Data.Vector as V+import OpenTelemetry.Exporter.InMemory.Span (inMemoryListExporter)+import OpenTelemetry.Instrumentation.Conduit (inSpan)+import OpenTelemetry.Trace.Core (Event (..))+import OpenTelemetry.Trace.Core hiding (inSpan)+import OpenTelemetry.Util (appendOnlyBoundedCollectionValues)+import System.IO.Error (userError)+import Test.Hspec+++main :: IO ()+main = hspec spec+++withTracer :: (Tracer -> IO a) -> IO ([ImmutableSpan], a)+withTracer action = do+  (processor, ref) <- inMemoryListExporter+  tp <- createTracerProvider [processor] emptyTracerProviderOptions+  let tracer = makeTracer tp "test-conduit" tracerOptions+  result <- action tracer+  _ <- shutdownTracerProvider tp Nothing+  spans <- readIORef ref+  pure (spans, result)+++firstSpan :: [ImmutableSpan] -> IO ImmutableSpan+firstSpan (s : _) = pure s+firstSpan [] = expectationFailure "No spans recorded" >> pure (error "unreachable")+++spec :: Spec+spec = describe "Conduit instrumentation" $ do+  it "creates a span wrapping a conduit pipeline" $ do+    (spans, result) <- withTracer $ \t ->+      runConduitRes $+        inSpan t "process-items" defaultSpanArguments $ \_s ->+          yieldMany [1 :: Int, 2, 3] .| sinkList+    result `shouldBe` [1, 2, 3]+    s <- firstSpan spans+    hot <- readIORef (spanHot s)+    hotName hot `shouldBe` "process-items"++  it "records exception on conduit failure" $ do+    (spans, result) <- withTracer $ \t -> do+      r <- try $+        runConduitRes $+          inSpan t "failing-conduit" defaultSpanArguments $ \_s ->+            yieldMany [1 :: Int, 2, 3] .| mapMC (\_ -> liftIO $ throwIO $ userError "conduit-boom") .| sinkList+      pure (r :: Either SomeException [Int])+    case result of+      Left _ -> pure ()+      Right _ -> expectationFailure "expected exception"+    s <- firstSpan spans+    hot <- readIORef (spanHot s)+    let events = V.toList $ appendOnlyBoundedCollectionValues $ hotEvents hot+    any (\e -> eventName e == "exception") events `shouldBe` True