Repository: open-telemetry/opentelemetry-python

Issue:
Jaeger Propagator not handling missing carrier
Python 3.8 / Flask injector 0.17b0


**Steps to reproduce**
If jaeger is the text map and you do not send a carrier header then the parser fails when it tries to parse the carrier header.

```python
        if context is None:
            context = get_current()
        fields = _extract_first_element(
            getter.get(carrier, self.TRACE_ID_KEY)
        ).split(":")
```

**What is the expected **
Parse as invalid span. Code continues.

**What is the actual behavior?**
```
File "/usr/local/lib/python3.8/site-packages/opentelemetry/propagators/jaeger/__init__.py", line 48, in extract
 fields = _extract_first_element(
AttributeError: 'NoneType' object has no attribute ‘split’
```

**Additional context**
TraceContextTextMapPropagator does this:

```python
        header = getter.get(carrier, self._TRACEPARENT_HEADER_NAME)

        if not header:
            return trace.set_span_in_context(trace.INVALID_SPAN, context)
```


Discussion:
It was not very clear from gitter discussion. IIUC it is giving error when the carrier doesn't have the propagation headers (for ex: `x-b3-traceid` or `uber-trace-id`) instead of setting invalid span context. I haven't looked at jaeger propagator code closely, but looks like this indeed is not expected behavior.

Resolving patch:
diff --git a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py
--- a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py
+++ b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py
@@ -45,9 +45,10 @@ def extract(
 
         if context is None:
             context = get_current()
-        fields = _extract_first_element(
-            getter.get(carrier, self.TRACE_ID_KEY)
-        ).split(":")
+        header = getter.get(carrier, self.TRACE_ID_KEY)
+        if not header:
+            return trace.set_span_in_context(trace.INVALID_SPAN, context)
+        fields = _extract_first_element(header).split(":")
 
         context = self._extract_baggage(getter, carrier, context)
         if len(fields) != 4:


Test patch:
diff --git a/propagator/opentelemetry-propagator-jaeger/tests/test_jaeger_propagator.py b/propagator/opentelemetry-propagator-jaeger/tests/test_jaeger_propagator.py
--- a/propagator/opentelemetry-propagator-jaeger/tests/test_jaeger_propagator.py
+++ b/propagator/opentelemetry-propagator-jaeger/tests/test_jaeger_propagator.py
@@ -83,6 +83,13 @@ def test_extract_valid_span(self):
         self.assertEqual(span_context.trace_id, self.trace_id)
         self.assertEqual(span_context.span_id, self.span_id)
 
+    def test_missing_carrier(self):
+        old_carrier = {}
+        ctx = FORMAT.extract(carrier_getter, old_carrier)
+        span_context = trace_api.get_current_span(ctx).get_span_context()
+        self.assertEqual(span_context.trace_id, trace_api.INVALID_TRACE_ID)
+        self.assertEqual(span_context.span_id, trace_api.INVALID_SPAN_ID)
+
     def test_trace_id(self):
         old_carrier = {FORMAT.TRACE_ID_KEY: self.serialized_uber_trace_id}
         _, new_carrier = get_context_new_carrier(old_carrier)