diff --git a/core-telemetry.cabal b/core-telemetry.cabal
--- a/core-telemetry.cabal
+++ b/core-telemetry.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           core-telemetry
-version:        0.1.9.4
+version:        0.2.0.1
 synopsis:       Advanced telemetry
 description:    This is part of a library to help build command-line programs, both tools and
                 longer-running daemons.
diff --git a/lib/Core/Telemetry/Identifiers.hs b/lib/Core/Telemetry/Identifiers.hs
--- a/lib/Core/Telemetry/Identifiers.hs
+++ b/lib/Core/Telemetry/Identifiers.hs
@@ -24,6 +24,7 @@
     createIdentifierSpan,
     hostMachineIdentity,
     createTraceParentHeader,
+    parseTraceParentHeader,
     -- for testing
     toHexNormal64,
     toHexReversed64,
@@ -37,6 +38,7 @@
 import Core.System.Base (liftIO)
 import Core.System.External (TimeStamp (unTimeStamp))
 import Core.Text.Rope
+import Core.Text.Utilities (breakPieces)
 import Data.Bits (shiftL, shiftR, (.&.), (.|.))
 import Data.Text.Internal.Unsafe.Char (unsafeChr8)
 import GHC.Word
@@ -74,7 +76,7 @@
 so that visual distinctiveness is on the left. The MAC address in the lower 48
 bits is /not/ reversed, leaving the most distinctiveness [the actual host as
 opposed to manufacturer OIN] hanging on the right hand edge of the identifier.
-The two bytes of randomness are in the middle.
+The two bytes of supplied randomness are put in the middle.
 
 @since 0.1.9
 -}
@@ -208,7 +210,7 @@
 {- |
 Generate an identifier for a span. We only have 8 bytes to work with. We use
 the nanosecond prescision timestamp with the nibbles reversed, and then
-overwrite the last two bytes with a random value.
+overwrite the last two bytes with the supplied random value.
 
 @since 0.1.9
 -}
@@ -226,12 +228,12 @@
 {- |
 Render the 'Trace' and 'Span' identifiers representing a span calling onward
 to another component in a distributed system. The W3C Trace Context
-recommendation specifies the HTTP header @traceparent@ with the 16 byte trace
-identifier and the 8 byte span identifier formatted as follows:
+recommendation specifies the HTTP header @traceparent@ with a version sequence
+(currently hard coded at @00@), the 16 byte trace identifier, the 8 byte span
+identifier, and a flag sequence (currently quite ignored), all formatted as
+follows:
 
-@
-traceparent: 00-fd533dbf96ecdc610156482ae36c24f7-1d1e9dbf96ec4649-00
-@
+@ traceparent: 00-fd533dbf96ecdc610156482ae36c24f7-1d1e9dbf96ec4649-00 @
 
 @since 0.1.9
 -}
@@ -242,8 +244,25 @@
      in version <> "-" <> unTrace trace <> "-" <> unSpan unique <> "-" <> flags
 
 {- |
+Parse a @traceparent@ header into a 'Trace' and 'Span', assuming it was a
+valid pair according to the W3C Trace Context recommendation. The expectation
+is that, if present in an HTTP request, these values would be passed to
+'Core.Telemetry.Observability.usingTrace' to allow the program to contribute
+spans to an existing trace started by another program or service.
+
+@since 0.1.10
+-}
+parseTraceParentHeader :: Rope -> Maybe (Trace, Span)
+parseTraceParentHeader header =
+    let pieces = breakPieces (== '-') header
+     in case pieces of
+            ("00" : trace : unique : _ : []) -> Just (Trace trace, Span unique)
+            _ -> Nothing
+
+{- |
 Get the identifier of the current trace, if you are within a trace started by
-'beginTrace' or 'usingTrace'.
+'Core.Telemetry.Observability.beginTrace' or
+'Core.Telemetry.Observability.usingTrace'.
 
 @since 0.1.9
 -}
@@ -259,7 +278,7 @@
 
 {- |
 Get the identifier of the current span, if you are currently within a span
-created by 'encloseSpan'.
+created by 'Core.Telemetry.Observability.encloseSpan'.
 
 @since 0.1.9
 -}
diff --git a/lib/Core/Telemetry/Observability.hs b/lib/Core/Telemetry/Observability.hs
--- a/lib/Core/Telemetry/Observability.hs
+++ b/lib/Core/Telemetry/Observability.hs
@@ -207,7 +207,7 @@
 contrast descibes the name of the current phase, step, or even function name
 within the overall scope of the \"service\".
 
-This will end up as the @service_name@ parameter when exported.
+This will end up as the @service.name@ parameter when exported.
 -}
 
 -- This field name appears to be very Honeycomb specific, but looking around
@@ -390,19 +390,17 @@
 encloseSpan label action = do
     context <- getContext
 
-    start <- liftIO $ do
-        getCurrentTimeNanoseconds
-
-    rand <- liftIO $ do
-        (randomIO :: IO Word16)
+    liftIO $ do
+        -- prepare new span
+        start <- getCurrentTimeNanoseconds
 
-    let unique = createIdentifierSpan start rand
+        rand <- randomIO :: IO Word16
 
-    internal label emptyRope
-    internal "span = " (unSpan unique)
+        let unique = createIdentifierSpan start rand
 
-    liftIO $ do
-        -- prepare new span
+        subProgram context $ do
+            internal ("Enter " <> label)
+            internal ("span = " <> unSpan unique)
 
         -- slightly tricky: create a new Context with a new MVar with an
         -- forked copy of the current Datum, creating the nested span.
@@ -431,6 +429,9 @@
             Safe.try
                 (subProgram context2 action)
 
+        subProgram context $ do
+            internal ("Leave " <> label)
+
         -- extract the Datum as it stands after running the action, finalize
         -- with its duration, and send it
         finish <- getCurrentTimeNanoseconds
@@ -473,18 +474,17 @@
 
     let trace = createIdentifierTrace now rand hostMachineIdentity
 
-    usingTrace trace Nothing action
+    internal "Begin trace"
+    internal ("trace = " <> unTrace trace)
 
-{- |
-Begin a new trace, but using a trace identifier provided externally. This is
-the most common case. Internal services that are play a part of a larger
-request will inherit a job identifier, sequence number, or other externally
-supplied unique code. Even an internet facing web service might have a
-correlation ID provided by the outside load balancers.
+    encloseTrace trace Nothing action
 
-If you are continuting an existing trace within the execution path of another,
-larger, enclosing service then you need to specify what the parent span's
-identifier is in the second argument.
+{- |
+Continue an existing trace using a 'Trace' identifier and parent 'Span'
+identifier sourced externally. This is the most common case. Internal services
+that play a part of a larger request will inherit a job identifier, sequence
+number, or other externally supplied unique code. Even an internet-facing web
+service might have a correlation ID provided by the outside load balancers.
 
 @
 program :: 'Core.Program.Execute.Program' 'Core.Program.Execute.None' ()
@@ -496,21 +496,24 @@
     -- and something to get the parent span ID
     parent <- ...
 
-    'usingTrace' ('Trace' trace) ('Just' ('Span' span)) $ do
+    'usingTrace' ('Trace' trace) ('Span' parent) $ do
         'encloseSpan' \"Internal processing\" $ do
             ...
 @
+
+@since 0.2.0
 -}
-usingTrace :: Trace -> Maybe Span -> Program τ α -> Program τ α
-usingTrace trace possibleParent action = do
-    context <- getContext
+usingTrace :: Trace -> Span -> Program τ α -> Program τ α
+usingTrace trace parent action = do
+    internal "Using trace"
+    internal ("trace = " <> unTrace trace)
+    internal ("parent = " <> unSpan parent)
 
-    case possibleParent of
-        Nothing -> do
-            internal "trace = " (unTrace trace)
-        Just parent -> do
-            internal "trace = " (unTrace trace)
-            internal "parent = " (unSpan parent)
+    encloseTrace trace (Just parent) action
+
+encloseTrace :: Trace -> Maybe Span -> Program τ α -> Program τ α
+encloseTrace trace possibleParent action = do
+    context <- getContext
 
     liftIO $ do
         -- prepare new span
