diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -2,6 +2,11 @@
 
 ## Unreleased
 
+## 0.3.1.0
+
+- Add `tracerIsEnabled` function to check if a Tracer is enabled (helps avoid expensive operations when tracing is disabled)
+- Fix `spanIdBaseEncodedByteString` error message
+
 ## 0.3.0.0
 
 - Export `fromList` from `OpenTelemetry.Trace.TraceState` for creating TraceState from key-value pairs
diff --git a/hs-opentelemetry-api.cabal b/hs-opentelemetry-api.cabal
--- a/hs-opentelemetry-api.cabal
+++ b/hs-opentelemetry-api.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:               hs-opentelemetry-api
-version:            0.3.0.0
+version:            0.3.1.0
 synopsis:           OpenTelemetry API for use by libraries for direct instrumentation or wrapper packages.
 description:        Please see the README on GitHub at <https://github.com/iand675/hs-opentelemetry/tree/main/api#readme>
 category:           OpenTelemetry, Telemetry, Monitoring, Observability, Metrics
@@ -120,6 +120,7 @@
       OpenTelemetry.SemanticsConfigSpec
       OpenTelemetry.Trace.SamplerSpec
       OpenTelemetry.Trace.TraceFlagsSpec
+      OpenTelemetry.Trace.TracerSpec
       Paths_hs_opentelemetry_api
   hs-source-dirs:
       test
diff --git a/src/OpenTelemetry/Internal/Trace/Id.hs b/src/OpenTelemetry/Internal/Trace/Id.hs
--- a/src/OpenTelemetry/Internal/Trace/Id.hs
+++ b/src/OpenTelemetry/Internal/Trace/Id.hs
@@ -153,7 +153,7 @@
 bytesToTraceId bs =
   if BS.length bs == 16
     then Right $ TraceId $ toShort bs
-    else Left "bytesToTraceId: TraceId must be 8 bytes long"
+    else Left "bytesToTraceId: TraceId must be 16 bytes long"
 
 
 {- | Convert a 'ByteString' of a specified base-encoding into a 'TraceId'.
diff --git a/src/OpenTelemetry/Trace/Core.hs b/src/OpenTelemetry/Trace/Core.hs
--- a/src/OpenTelemetry/Trace/Core.hs
+++ b/src/OpenTelemetry/Trace/Core.hs
@@ -60,6 +60,7 @@
   -- * @Tracer@ operations
   Tracer,
   tracerName,
+  tracerIsEnabled,
   HasTracer (..),
   makeTracer,
   getTracer,
@@ -878,6 +879,21 @@
 
 getTracerTracerProvider :: Tracer -> TracerProvider
 getTracerTracerProvider = tracerProvider
+
+
+{- | Check if the 'Tracer' is enabled.
+
+ This function helps users avoid performing computationally expensive operations
+ when creating 'Span's if the tracer is not enabled.
+
+ A 'Tracer' is considered enabled if it has at least one configured processor.
+ If the 'TracerProvider' has no processors, all spans will be dropped, so the
+ tracer is disabled.
+
+ @since 0.3.1.0
+-}
+tracerIsEnabled :: Tracer -> Bool
+tracerIsEnabled t = not $ V.null $ tracerProviderProcessors $ tracerProvider t
 
 
 {- | Smart constructor for 'SpanArguments' providing reasonable values for most 'Span's created
diff --git a/test/OpenTelemetry/Trace/TracerSpec.hs b/test/OpenTelemetry/Trace/TracerSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/OpenTelemetry/Trace/TracerSpec.hs
@@ -0,0 +1,50 @@
+module OpenTelemetry.Trace.TracerSpec where
+
+import qualified OpenTelemetry.Attributes as A
+import OpenTelemetry.Processor.Span (SpanProcessor (..))
+import OpenTelemetry.Trace.Core
+import OpenTelemetry.Trace.Sampler
+import Test.Hspec
+
+
+spec :: Spec
+spec = describe "Tracer" $ do
+  describe "tracerIsEnabled" $ do
+    it "returns False when TracerProvider has no processors" $ do
+      tp <- createTracerProvider [] emptyTracerProviderOptions
+      let instrLib = InstrumentationLibrary "test" "1.0.0" "" A.emptyAttributes
+          tracer = makeTracer tp instrLib tracerOptions
+      tracerIsEnabled tracer `shouldBe` False
+
+    it "returns True when TracerProvider has at least one processor" $ do
+      let dummyProcessor =
+            SpanProcessor
+              { spanProcessorOnStart = \_ _ -> pure ()
+              , spanProcessorOnEnd = \_ -> pure ()
+              , spanProcessorShutdown = error "not implemented in test"
+              , spanProcessorForceFlush = pure ()
+              }
+      tp <- createTracerProvider [dummyProcessor] emptyTracerProviderOptions
+      let instrLib = InstrumentationLibrary "test" "1.0.0" "" A.emptyAttributes
+          tracer = makeTracer tp instrLib tracerOptions
+      tracerIsEnabled tracer `shouldBe` True
+
+    it "returns True when TracerProvider has multiple processors" $ do
+      let dummyProcessor1 =
+            SpanProcessor
+              { spanProcessorOnStart = \_ _ -> pure ()
+              , spanProcessorOnEnd = \_ -> pure ()
+              , spanProcessorShutdown = error "not implemented in test"
+              , spanProcessorForceFlush = pure ()
+              }
+          dummyProcessor2 =
+            SpanProcessor
+              { spanProcessorOnStart = \_ _ -> pure ()
+              , spanProcessorOnEnd = \_ -> pure ()
+              , spanProcessorShutdown = error "not implemented in test"
+              , spanProcessorForceFlush = pure ()
+              }
+      tp <- createTracerProvider [dummyProcessor1, dummyProcessor2] emptyTracerProviderOptions
+      let instrLib = InstrumentationLibrary "test" "1.0.0" "" A.emptyAttributes
+          tracer = makeTracer tp instrLib tracerOptions
+      tracerIsEnabled tracer `shouldBe` True
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -21,6 +21,7 @@
 import OpenTelemetry.Trace.Core
 import qualified OpenTelemetry.Trace.SamplerSpec as Sampler
 import qualified OpenTelemetry.Trace.TraceFlagsSpec as TraceFlags
+import qualified OpenTelemetry.Trace.TracerSpec as Tracer
 import OpenTelemetry.Util
 import Test.Hspec
 import qualified VectorBuilder.Vector as Builder
@@ -62,5 +63,6 @@
   InstrumentationLibrary.spec
   Sampler.spec
   TraceFlags.spec
+  Tracer.spec
   SemanticsConfigSpec.spec
   CoreSpec.spec
