packages feed

shibuya-core 0.5.0.0 → 0.6.0.0

raw patch · 7 files changed

+65/−46 lines, 7 files

Files

CHANGELOG.md view
@@ -1,5 +1,27 @@ # Changelog +## 0.6.0.0 — 2026-05-31++### Breaking Changes++- OpenTelemetry messaging spans now emit `messaging.operation.type =+  "process"` instead of the deprecated `messaging.operation = "process"`+  wire key. The Haskell constant `attrMessagingOperation` keeps the same+  name and now resolves to the current semantic-conventions key, so source+  imports continue to compile. Dashboards, alerts, and trace queries that+  filter on `messaging.operation` must be updated to+  `messaging.operation.type`.++### Other Changes++- Upgrade OpenTelemetry dependencies to the 1.0 ecosystem:+  `hs-opentelemetry-api ^>= 1.0`,+  `hs-opentelemetry-propagator-w3c ^>= 1.0`, and test-only+  `hs-opentelemetry-exporter-in-memory ^>= 1.0`.+- Move `hs-opentelemetry-semantic-conventions` to the latest Haskell+  generated package available with the 1.0 release, `^>= 1.40`, and source+  Shibuya's generic messaging keys from its typed exports.+ ## 0.5.0.0 — 2026-05-05  ### Breaking Changes
shibuya-core.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.14 name: shibuya-core-version: 0.5.0.0+version: 0.6.0.0 synopsis: Supervised queue processing framework for Haskell description:   A supervised queue processing framework inspired by Broadway (Elixir).@@ -70,9 +70,9 @@     effectful ^>=2.6.1.0,     effectful-core ^>=2.6.1.0,     generic-lens ^>=2.3.0.0,-    hs-opentelemetry-api ^>=0.3,-    hs-opentelemetry-propagator-w3c ^>=0.1,-    hs-opentelemetry-semantic-conventions ^>=0.1,+    hs-opentelemetry-api ^>=1.0,+    hs-opentelemetry-propagator-w3c ^>=1.0,+    hs-opentelemetry-semantic-conventions ^>=1.40,     lens ^>=5.3.5,     nqe ^>=0.6,     random ^>=1.2,@@ -128,9 +128,8 @@     bytestring,     effectful,     hs-opentelemetry-api,-    hs-opentelemetry-exporter-in-memory ^>=0.0,+    hs-opentelemetry-exporter-in-memory ^>=1.0,     hspec ^>=2.11,-    memory,     nqe,     shibuya-core,     stm,
src/Shibuya/Core/Types.hs view
@@ -23,7 +23,7 @@ import Data.ByteString (ByteString) import Data.HashMap.Strict (HashMap) import Data.String (IsString)-import OpenTelemetry.Attributes (Attribute (..), PrimitiveAttribute (..))+import OpenTelemetry.Attributes (Attribute (..)) import Shibuya.Prelude  -- | Stable identity for idempotency & observability.
src/Shibuya/Telemetry/Effect.hs view
@@ -38,7 +38,7 @@   ) where -import Control.Exception (Exception, bracket_)+import Control.Exception (Exception, bracket) import Data.ByteString qualified as BS import Data.HashMap.Strict (HashMap) import Data.HashMap.Strict qualified as HashMap@@ -280,10 +280,10 @@       let parentSpan = OTel.wrapSpanContext parentCtx           newContext = Ctx.insertSpan parentSpan Ctx.empty       withEffToIO (ConcUnlift Persistent Unlimited) $ \runInIO ->-        bracket_+        bracket           (Ctx.attachContext newContext)           Ctx.detachContext-          (runInIO action)+          (\_token -> runInIO action)  -------------------------------------------------------------------------------- -- Internal Helpers
src/Shibuya/Telemetry/Semantic.hs view
@@ -91,12 +91,12 @@ attrMessagingDestinationName :: Text attrMessagingDestinationName = unkey Sem.messaging_destination_name --- | The messaging operation (@messaging.operation@).+-- | The messaging operation type (@messaging.operation.type@). ----- One of the spec-defined enum values: @publish@, @receive@, @process@,--- @settle@, @create@. Shibuya's per-message span uses @"process"@.+-- One of the spec-defined enum values: @create@, @send@, @receive@,+-- @process@, @settle@. Shibuya's per-message span uses @"process"@. attrMessagingOperation :: Text-attrMessagingOperation = unkey Sem.messaging_operation+attrMessagingOperation = unkey Sem.messaging_operation_type  -------------------------------------------------------------------------------- -- Attribute Keys (Shibuya-specific)@@ -129,7 +129,7 @@  -- | A generic partition identifier (@shibuya.partition@). ----- Shibuya-specific: in semantic-conventions v1.24 there is no portable+-- Shibuya-specific: there is no portable -- @messaging.destination.partition.id@ key — only system-specific ones -- (@messaging.kafka.destination.partition@, -- @messaging.eventhubs.destination.partition.id@). System-specific
test/Shibuya/Telemetry/PropagationSpec.hs view
@@ -3,10 +3,10 @@ -- | Tests for W3C Trace Context propagation. module Shibuya.Telemetry.PropagationSpec (spec) where -import Data.ByteArray.Encoding (Base (..)) import Data.ByteString (ByteString) import Effectful (runEff) import OpenTelemetry.Attributes (emptyAttributes)+import OpenTelemetry.Exporter.InMemory (inMemoryListExporter) import OpenTelemetry.Trace.Core   ( InstrumentationLibrary (..),     createTracerProvider,@@ -17,6 +17,7 @@     tracerOptions,   ) import OpenTelemetry.Trace.Core qualified as OTel+import OpenTelemetry.Trace.Id (Base (..)) import OpenTelemetry.Trace.Id qualified as OTel.Id import Shibuya.Telemetry.Effect (runTracing, runTracingNoop, withSpan) import Shibuya.Telemetry.Propagation (currentTraceHeaders, extractTraceContext)@@ -60,38 +61,29 @@           headers = [("traceparent", "invalid-format")]       extractTraceContext headers `shouldBe` Nothing -    it "parses traceparent with non-standard version (permissive)" $ do-      -- Note: hs-opentelemetry propagator is permissive and accepts non-00 versions+    it "rejects traceparent with non-standard version" $ do+      -- hs-opentelemetry 1.0 validates the traceparent version strictly.       let headers :: [(ByteString, ByteString)]           headers =             [ ("traceparent", "ff-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01")             ]-      -- Library accepts this - validation is left to the application-      case extractTraceContext headers of-        Nothing -> expectationFailure "Library should parse non-standard version"-        Just _ctx -> pure ()+      extractTraceContext headers `shouldBe` Nothing -    it "parses traceparent with all-zero trace ID (permissive)" $ do-      -- Note: hs-opentelemetry propagator doesn't reject all-zero trace IDs+    it "rejects traceparent with all-zero trace ID" $ do+      -- hs-opentelemetry 1.0 rejects all-zero trace IDs.       let headers :: [(ByteString, ByteString)]           headers =             [ ("traceparent", "00-00000000000000000000000000000000-b7ad6b7169203331-01")             ]-      -- Library accepts this - validation is left to the application-      case extractTraceContext headers of-        Nothing -> expectationFailure "Library should parse all-zero trace ID"-        Just ctx -> OTel.Id.traceIdBaseEncodedText Base16 (OTel.traceId ctx) `shouldBe` "00000000000000000000000000000000"+      extractTraceContext headers `shouldBe` Nothing -    it "parses traceparent with all-zero span ID (permissive)" $ do-      -- Note: hs-opentelemetry propagator doesn't reject all-zero span IDs+    it "rejects traceparent with all-zero span ID" $ do+      -- hs-opentelemetry 1.0 rejects all-zero span IDs.       let headers :: [(ByteString, ByteString)]           headers =             [ ("traceparent", "00-0af7651916cd43dd8448eb211c80319c-0000000000000000-01")             ]-      -- Library accepts this - validation is left to the application-      case extractTraceContext headers of-        Nothing -> expectationFailure "Library should parse all-zero span ID"-        Just ctx -> OTel.Id.spanIdBaseEncodedText Base16 (OTel.spanId ctx) `shouldBe` "0000000000000000"+      extractTraceContext headers `shouldBe` Nothing      it "handles unsampled trace flag (00)" $ do       let headers :: [(ByteString, ByteString)]@@ -151,11 +143,12 @@               )               tracerOptions       result <- runEff $ runTracing tracer currentTraceHeaders-      _ <- shutdownTracerProvider provider+      _ <- shutdownTracerProvider provider (Just 5_000_000)       result `shouldBe` Nothing      it "returns headers carrying the active span's traceparent" $ do-      provider <- createTracerProvider [] emptyTracerProviderOptions+      (processor, _spansRef) <- inMemoryListExporter+      provider <- createTracerProvider [processor] emptyTracerProviderOptions       let tracer =             makeTracer               provider@@ -168,7 +161,7 @@               )               tracerOptions       result <- runEff $ runTracing tracer $ withSpan "outer" defaultSpanArguments currentTraceHeaders-      _ <- shutdownTracerProvider provider+      _ <- shutdownTracerProvider provider (Just 5_000_000)       case result of         Nothing -> expectationFailure "expected currentTraceHeaders to return Just"         Just hs -> case lookup "traceparent" hs of
test/Shibuya/Telemetry/SemanticSpec.hs view
@@ -24,13 +24,16 @@     getAttributeMap,     toAttribute,   )-import OpenTelemetry.Exporter.InMemory.Span (inMemoryListExporter)+import OpenTelemetry.Exporter.InMemory (inMemoryListExporter) import OpenTelemetry.Trace.Core   ( Event (..),     ImmutableSpan (..),     InstrumentationLibrary (..),     createTracerProvider,     emptyTracerProviderOptions,+    hotAttributes,+    hotEvents,+    hotName,     makeTracer,     shutdownTracerProvider,     tracerOptions,@@ -77,20 +80,21 @@       _ <- runWithMetrics 4 procId adapter handler       pure () -    _ <- shutdownTracerProvider provider+    _ <- shutdownTracerProvider provider (Just 5_000_000)     spans <- readIORef spansRef     case spans of       [s] -> do-        spanName s `shouldBe` "test-proc process"-        let attrs = getAttributeMap (spanAttributes s)+        hot <- readIORef (spanHot s)+        hotName hot `shouldBe` "test-proc process"+        let attrs = getAttributeMap (hotAttributes hot)         attrs `shouldHaveTextAttribute` ("messaging.system", "shibuya")         attrs `shouldHaveTextAttribute` ("messaging.message.id", "m-1")         attrs `shouldHaveTextAttribute` ("messaging.destination.name", "test-proc")-        attrs `shouldHaveTextAttribute` ("messaging.operation", "process")+        attrs `shouldHaveTextAttribute` ("messaging.operation.type", "process")         attrs `shouldHaveTextAttribute` ("shibuya.ack.decision", "ack_ok")         attrs `shouldHaveIntAttribute` ("shibuya.inflight.count", 1)         attrs `shouldHaveIntAttribute` ("shibuya.inflight.max", 1)-        let evNames = map eventName (toList (appendOnlyBoundedCollectionValues (spanEvents s)))+        let evNames = map eventName (toList (appendOnlyBoundedCollectionValues (hotEvents hot)))         evNames `shouldContain` ["shibuya.handler.started"]         evNames `shouldContain` ["shibuya.handler.completed"]       _ ->@@ -139,11 +143,12 @@       _ <- runWithMetrics 4 procId adapter handler       pure () -    _ <- shutdownTracerProvider provider+    _ <- shutdownTracerProvider provider (Just 5_000_000)     spans <- readIORef spansRef     case spans of       [s] -> do-        let attrs = getAttributeMap (spanAttributes s)+        hot <- readIORef (spanHot s)+        let attrs = getAttributeMap (hotAttributes hot)         -- Adapter override wins.         attrs `shouldHaveTextAttribute` ("messaging.system", "kafka")         -- Adapter-typed attributes appear on the framework span.@@ -151,7 +156,7 @@         attrs `shouldHaveIntAttribute` ("messaging.kafka.message.offset", 42)         -- Framework defaults still set where the adapter did not override.         attrs `shouldHaveTextAttribute` ("messaging.destination.name", "orders-consumer")-        attrs `shouldHaveTextAttribute` ("messaging.operation", "process")+        attrs `shouldHaveTextAttribute` ("messaging.operation.type", "process")         attrs `shouldHaveTextAttribute` ("messaging.message.id", "orders-2-42")       _ ->         expectationFailure $