hs-opentelemetry-api
Copyright(c) Ian Duncan 2024
LicenseBSD-3
MaintainerIan Duncan
Stabilityalpha
Portabilitynon-portable (GHC extensions)
Safe HaskellNone
LanguageHaskell2010

OpenTelemetry.Context.Environment

Description

This module implements the Environment Variables as Context Propagation Carriers specification (Alpha).

It uses the globally configured TextMapPropagator to inject/extract trace context through environment variables. Propagation field names are normalized to POSIX-compatible environment variable names per the specification, making this module format-agnostic: it works with W3C, B3, Datadog, or any other registered propagator.

Usage

Extracting context in a child process (at startup):

main :: IO ()
main = do
  ctx <- extractContextFromEnvironment
  _tok <- attachContext ctx
  -- ... this process is now part of the parent's trace

Injecting context when spawning a child process:

import System.Process (CreateProcess, proc, createProcess)
import System.Environment (getEnvironment)

spawnTracedChild :: IO ()
spawnTracedChild = do
  baseEnv <- getEnvironment
  traceEnv <- injectCurrentContextToEnvironment
  let childEnv = mergeEnvironment traceEnv baseEnv
  createProcess (proc "my-child" []) { env = Just childEnv }

Spec compliance

Per the specification, this module does not handle process spawning. The application is responsible for passing the injected environment variables to its process-spawning mechanism.

The carrier is format-agnostic: key normalization follows POSIX rules (uppercase, replace non-alphanumeric/non-underscore with _, prefix with _ if the name would start with a digit). Values are treated as opaque strings.

Since: 0.4.0.0

Synopsis

Extract (child process startup)

extractContextFromEnvironment :: IO Context Source #

Extract trace context from the current process's environment variables.

Reads all environment variables, reverse-normalizes their names to propagation field equivalents, and delegates to the globally configured TextMapPropagator for parsing. The propagator determines which variables are relevant (e.g. TRACEPARENT for W3C, X_B3_TRACEID for B3).

Returns the current thread-local context enriched with any extracted span context and baggage. If the environment variables are absent or unparseable, the original context is returned unchanged.

Since: 0.4.0.0

Inject (before spawning child)

injectContextToEnvironment :: Context -> IO [(String, String)] Source #

Inject the given context into a list of environment variable key-value pairs.

Uses the globally configured TextMapPropagator to serialize trace context and baggage, then normalizes the resulting field names to POSIX-compatible environment variable names.

The returned list contains only the trace-related variables. Use mergeEnvironment to combine them with the current process environment before passing to CreateProcess.

Since: 0.4.0.0

injectCurrentContextToEnvironment :: IO [(String, String)] Source #

Convenience wrapper: injects the current thread-local context.

Equivalent to getContext >>= injectContextToEnvironment.

Since: 0.4.0.0

Helpers

mergeEnvironment Source #

Arguments

:: [(String, String)]

Trace environment variables (take precedence)

-> [(String, String)]

Base environment

-> [(String, String)] 

Merge trace environment variables into a base environment.

Later entries (the base) are overwritten by earlier entries (the trace vars) for matching keys. This is the intended merge direction: trace context should override any stale TRACEPARENT etc. that may exist in the inherited environment.

baseEnv <- getEnvironment
traceEnv <- injectCurrentContextToEnvironment
let childEnv = mergeEnvironment traceEnv baseEnv

Since: 0.4.0.0

Key normalization

normalizeKeyToEnvVar :: Text -> String Source #

Normalize a propagation field name to a POSIX-compatible environment variable name.

Per the OTel spec, environment variable names:

  • MUST have ASCII letters uppercased
  • MUST have every character that is not an ASCII letter, digit, or underscore replaced with an underscore
  • MUST be prefixed with _ if the result would start with a digit

Examples:

normalizeKeyToEnvVar "traceparent"     == TRACEPARENT
normalizeKeyToEnvVar "x-b3-traceid"   == X_B3_TRACEID
normalizeKeyToEnvVar "x-datadog-trace" == X_DATADOG_TRACE

Since: 0.4.0.0

Well-known environment variable names

envTraceparent :: String Source #

Since: 0.4.0.0

envTracestate :: String Source #

Since: 0.4.0.0

envBaggage :: String Source #

Since: 0.4.0.0