We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
AttributeError: 'NonRecordingSpan' object has no attribute 'parent'
[Environment]
------------------------------------------
python==3.7.1
opentelemetry-api==1.7.1
opentelemetry-exporter-jaeger==1.7.1
opentelemetry-propagator-jaeger==1.7.1
opentelemetry-sdk==1.7.1

OTEL_TRACES_SAMPLER=traceidratio
OTEL_TRACES_SAMPLER_ARG=0

My Code :
![image](https://user-images.githubusercontent.com/16707489/147833466-782cd3df-9490-4a30-b44c-c258681e1931.png)


[Issue]
------------------------------------------
0 rate for TraceIdRatioBased sampler to create the NonRecordingSpan, which with no `parent` attribute. 
Then I try to inject carrier with Jaeger Propagator. Following exception happened:
`
'NonRecordingSpan' object has no attribute 'parent'
 File "/usr/local/lib/python3.7/dist-packages/opentelemetry/propagators/jaeger/__init__.py", line 84, in inject
    span_parent_id = span.parent.span_id if span.parent else 0
`

[expected behavior]
----------------------------------
It should return with empty carrier without any exception.

AttributeError: 'NonRecordingSpan' object has no attribute 'parent'
[Environment]
------------------------------------------
python==3.7.1
opentelemetry-api==1.7.1
opentelemetry-exporter-jaeger==1.7.1
opentelemetry-propagator-jaeger==1.7.1
opentelemetry-sdk==1.7.1

OTEL_TRACES_SAMPLER=traceidratio
OTEL_TRACES_SAMPLER_ARG=0

My Code :
![image](https://user-images.githubusercontent.com/16707489/147833466-782cd3df-9490-4a30-b44c-c258681e1931.png)


[Issue]
------------------------------------------
0 rate for TraceIdRatioBased sampler to create the NonRecordingSpan, which with no `parent` attribute. 
Then I try to inject carrier with Jaeger Propagator. Following exception happened:
`
'NonRecordingSpan' object has no attribute 'parent'
 File "/usr/local/lib/python3.7/dist-packages/opentelemetry/propagators/jaeger/__init__.py", line 84, in inject
    span_parent_id = span.parent.span_id if span.parent else 0
`

[expected behavior]
----------------------------------
It should return with empty carrier without any exception.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py`
Content:
```
1 # Copyright The OpenTelemetry Authors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import typing
16 import urllib.parse
17 
18 from opentelemetry import baggage, trace
19 from opentelemetry.context import Context
20 from opentelemetry.propagators.textmap import (
21     CarrierT,
22     Getter,
23     Setter,
24     TextMapPropagator,
25     default_getter,
26     default_setter,
27 )
28 from opentelemetry.trace import format_span_id, format_trace_id
29 
30 
31 class JaegerPropagator(TextMapPropagator):
32     """Propagator for the Jaeger format.
33 
34     See: https://www.jaegertracing.io/docs/1.19/client-libraries/#propagation-format
35     """
36 
37     TRACE_ID_KEY = "uber-trace-id"
38     BAGGAGE_PREFIX = "uberctx-"
39     DEBUG_FLAG = 0x02
40 
41     def extract(
42         self,
43         carrier: CarrierT,
44         context: typing.Optional[Context] = None,
45         getter: Getter = default_getter,
46     ) -> Context:
47 
48         if context is None:
49             context = Context()
50         header = getter.get(carrier, self.TRACE_ID_KEY)
51         if not header:
52             return context
53 
54         context = self._extract_baggage(getter, carrier, context)
55 
56         trace_id, span_id, flags = _parse_trace_id_header(header)
57         if (
58             trace_id == trace.INVALID_TRACE_ID
59             or span_id == trace.INVALID_SPAN_ID
60         ):
61             return context
62 
63         span = trace.NonRecordingSpan(
64             trace.SpanContext(
65                 trace_id=trace_id,
66                 span_id=span_id,
67                 is_remote=True,
68                 trace_flags=trace.TraceFlags(flags & trace.TraceFlags.SAMPLED),
69             )
70         )
71         return trace.set_span_in_context(span, context)
72 
73     def inject(
74         self,
75         carrier: CarrierT,
76         context: typing.Optional[Context] = None,
77         setter: Setter = default_setter,
78     ) -> None:
79         span = trace.get_current_span(context=context)
80         span_context = span.get_span_context()
81         if span_context == trace.INVALID_SPAN_CONTEXT:
82             return
83 
84         span_parent_id = span.parent.span_id if span.parent else 0
85         trace_flags = span_context.trace_flags
86         if trace_flags.sampled:
87             trace_flags |= self.DEBUG_FLAG
88 
89         # set span identity
90         setter.set(
91             carrier,
92             self.TRACE_ID_KEY,
93             _format_uber_trace_id(
94                 span_context.trace_id,
95                 span_context.span_id,
96                 span_parent_id,
97                 trace_flags,
98             ),
99         )
100 
101         # set span baggage, if any
102         baggage_entries = baggage.get_all(context=context)
103         if not baggage_entries:
104             return
105         for key, value in baggage_entries.items():
106             baggage_key = self.BAGGAGE_PREFIX + key
107             setter.set(carrier, baggage_key, urllib.parse.quote(str(value)))
108 
109     @property
110     def fields(self) -> typing.Set[str]:
111         return {self.TRACE_ID_KEY}
112 
113     def _extract_baggage(self, getter, carrier, context):
114         baggage_keys = [
115             key
116             for key in getter.keys(carrier)
117             if key.startswith(self.BAGGAGE_PREFIX)
118         ]
119         for key in baggage_keys:
120             value = _extract_first_element(getter.get(carrier, key))
121             context = baggage.set_baggage(
122                 key.replace(self.BAGGAGE_PREFIX, ""),
123                 urllib.parse.unquote(value).strip(),
124                 context=context,
125             )
126         return context
127 
128 
129 def _format_uber_trace_id(trace_id, span_id, parent_span_id, flags):
130     return f"{format_trace_id(trace_id)}:{format_span_id(span_id)}:{format_span_id(parent_span_id)}:{flags:02x}"
131 
132 
133 def _extract_first_element(
134     items: typing.Iterable[CarrierT],
135 ) -> typing.Optional[CarrierT]:
136     if items is None:
137         return None
138     return next(iter(items), None)
139 
140 
141 def _parse_trace_id_header(
142     items: typing.Iterable[CarrierT],
143 ) -> typing.Tuple[int]:
144     invalid_header_result = (trace.INVALID_TRACE_ID, trace.INVALID_SPAN_ID, 0)
145 
146     header = _extract_first_element(items)
147     if header is None:
148         return invalid_header_result
149 
150     fields = header.split(":")
151     if len(fields) != 4:
152         return invalid_header_result
153 
154     trace_id_str, span_id_str, _parent_id_str, flags_str = fields
155     flags = _int_from_hex_str(flags_str, None)
156     if flags is None:
157         return invalid_header_result
158 
159     trace_id = _int_from_hex_str(trace_id_str, trace.INVALID_TRACE_ID)
160     span_id = _int_from_hex_str(span_id_str, trace.INVALID_SPAN_ID)
161     return trace_id, span_id, flags
162 
163 
164 def _int_from_hex_str(
165     identifier: str, default: typing.Optional[int]
166 ) -> typing.Optional[int]:
167     try:
168         return int(identifier, 16)
169     except ValueError:
170         return default
171
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

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
@@ -81,7 +81,10 @@
         if span_context == trace.INVALID_SPAN_CONTEXT:
             return
 
-        span_parent_id = span.parent.span_id if span.parent else 0
+        # Non-recording spans do not have a parent
+        span_parent_id = (
+            span.parent.span_id if span.is_recording() and span.parent else 0
+        )
         trace_flags = span_context.trace_flags
         if trace_flags.sampled:
             trace_flags |= self.DEBUG_FLAG

{"golden_diff": "diff --git a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py\n--- a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py\n+++ b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py\n@@ -81,7 +81,10 @@\n         if span_context == trace.INVALID_SPAN_CONTEXT:\n             return\n \n-        span_parent_id = span.parent.span_id if span.parent else 0\n+        # Non-recording spans do not have a parent\n+        span_parent_id = (\n+            span.parent.span_id if span.is_recording() and span.parent else 0\n+        )\n         trace_flags = span_context.trace_flags\n         if trace_flags.sampled:\n             trace_flags |= self.DEBUG_FLAG\n", "issue": "AttributeError: 'NonRecordingSpan' object has no attribute 'parent'\n[Environment]\r\n------------------------------------------\r\npython==3.7.1\r\nopentelemetry-api==1.7.1\r\nopentelemetry-exporter-jaeger==1.7.1\r\nopentelemetry-propagator-jaeger==1.7.1\r\nopentelemetry-sdk==1.7.1\r\n\r\nOTEL_TRACES_SAMPLER=traceidratio\r\nOTEL_TRACES_SAMPLER_ARG=0\r\n\r\nMy Code :\r\n![image](https://user-images.githubusercontent.com/16707489/147833466-782cd3df-9490-4a30-b44c-c258681e1931.png)\r\n\r\n\r\n[Issue]\r\n------------------------------------------\r\n0 rate for TraceIdRatioBased sampler to create the NonRecordingSpan, which with no `parent` attribute. \r\nThen I try to inject carrier with Jaeger Propagator. Following exception happened:\r\n`\r\n'NonRecordingSpan' object has no attribute 'parent'\r\n File \"/usr/local/lib/python3.7/dist-packages/opentelemetry/propagators/jaeger/__init__.py\", line 84, in inject\r\n    span_parent_id = span.parent.span_id if span.parent else 0\r\n`\r\n\r\n[expected behavior]\r\n----------------------------------\r\nIt should return with empty carrier without any exception.\r\n\nAttributeError: 'NonRecordingSpan' object has no attribute 'parent'\n[Environment]\r\n------------------------------------------\r\npython==3.7.1\r\nopentelemetry-api==1.7.1\r\nopentelemetry-exporter-jaeger==1.7.1\r\nopentelemetry-propagator-jaeger==1.7.1\r\nopentelemetry-sdk==1.7.1\r\n\r\nOTEL_TRACES_SAMPLER=traceidratio\r\nOTEL_TRACES_SAMPLER_ARG=0\r\n\r\nMy Code :\r\n![image](https://user-images.githubusercontent.com/16707489/147833466-782cd3df-9490-4a30-b44c-c258681e1931.png)\r\n\r\n\r\n[Issue]\r\n------------------------------------------\r\n0 rate for TraceIdRatioBased sampler to create the NonRecordingSpan, which with no `parent` attribute. \r\nThen I try to inject carrier with Jaeger Propagator. Following exception happened:\r\n`\r\n'NonRecordingSpan' object has no attribute 'parent'\r\n File \"/usr/local/lib/python3.7/dist-packages/opentelemetry/propagators/jaeger/__init__.py\", line 84, in inject\r\n    span_parent_id = span.parent.span_id if span.parent else 0\r\n`\r\n\r\n[expected behavior]\r\n----------------------------------\r\nIt should return with empty carrier without any exception.\r\n\n", "before_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport typing\nimport urllib.parse\n\nfrom opentelemetry import baggage, trace\nfrom opentelemetry.context import Context\nfrom opentelemetry.propagators.textmap import (\n    CarrierT,\n    Getter,\n    Setter,\n    TextMapPropagator,\n    default_getter,\n    default_setter,\n)\nfrom opentelemetry.trace import format_span_id, format_trace_id\n\n\nclass JaegerPropagator(TextMapPropagator):\n    \"\"\"Propagator for the Jaeger format.\n\n    See: https://www.jaegertracing.io/docs/1.19/client-libraries/#propagation-format\n    \"\"\"\n\n    TRACE_ID_KEY = \"uber-trace-id\"\n    BAGGAGE_PREFIX = \"uberctx-\"\n    DEBUG_FLAG = 0x02\n\n    def extract(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        getter: Getter = default_getter,\n    ) -> Context:\n\n        if context is None:\n            context = Context()\n        header = getter.get(carrier, self.TRACE_ID_KEY)\n        if not header:\n            return context\n\n        context = self._extract_baggage(getter, carrier, context)\n\n        trace_id, span_id, flags = _parse_trace_id_header(header)\n        if (\n            trace_id == trace.INVALID_TRACE_ID\n            or span_id == trace.INVALID_SPAN_ID\n        ):\n            return context\n\n        span = trace.NonRecordingSpan(\n            trace.SpanContext(\n                trace_id=trace_id,\n                span_id=span_id,\n                is_remote=True,\n                trace_flags=trace.TraceFlags(flags & trace.TraceFlags.SAMPLED),\n            )\n        )\n        return trace.set_span_in_context(span, context)\n\n    def inject(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        setter: Setter = default_setter,\n    ) -> None:\n        span = trace.get_current_span(context=context)\n        span_context = span.get_span_context()\n        if span_context == trace.INVALID_SPAN_CONTEXT:\n            return\n\n        span_parent_id = span.parent.span_id if span.parent else 0\n        trace_flags = span_context.trace_flags\n        if trace_flags.sampled:\n            trace_flags |= self.DEBUG_FLAG\n\n        # set span identity\n        setter.set(\n            carrier,\n            self.TRACE_ID_KEY,\n            _format_uber_trace_id(\n                span_context.trace_id,\n                span_context.span_id,\n                span_parent_id,\n                trace_flags,\n            ),\n        )\n\n        # set span baggage, if any\n        baggage_entries = baggage.get_all(context=context)\n        if not baggage_entries:\n            return\n        for key, value in baggage_entries.items():\n            baggage_key = self.BAGGAGE_PREFIX + key\n            setter.set(carrier, baggage_key, urllib.parse.quote(str(value)))\n\n    @property\n    def fields(self) -> typing.Set[str]:\n        return {self.TRACE_ID_KEY}\n\n    def _extract_baggage(self, getter, carrier, context):\n        baggage_keys = [\n            key\n            for key in getter.keys(carrier)\n            if key.startswith(self.BAGGAGE_PREFIX)\n        ]\n        for key in baggage_keys:\n            value = _extract_first_element(getter.get(carrier, key))\n            context = baggage.set_baggage(\n                key.replace(self.BAGGAGE_PREFIX, \"\"),\n                urllib.parse.unquote(value).strip(),\n                context=context,\n            )\n        return context\n\n\ndef _format_uber_trace_id(trace_id, span_id, parent_span_id, flags):\n    return f\"{format_trace_id(trace_id)}:{format_span_id(span_id)}:{format_span_id(parent_span_id)}:{flags:02x}\"\n\n\ndef _extract_first_element(\n    items: typing.Iterable[CarrierT],\n) -> typing.Optional[CarrierT]:\n    if items is None:\n        return None\n    return next(iter(items), None)\n\n\ndef _parse_trace_id_header(\n    items: typing.Iterable[CarrierT],\n) -> typing.Tuple[int]:\n    invalid_header_result = (trace.INVALID_TRACE_ID, trace.INVALID_SPAN_ID, 0)\n\n    header = _extract_first_element(items)\n    if header is None:\n        return invalid_header_result\n\n    fields = header.split(\":\")\n    if len(fields) != 4:\n        return invalid_header_result\n\n    trace_id_str, span_id_str, _parent_id_str, flags_str = fields\n    flags = _int_from_hex_str(flags_str, None)\n    if flags is None:\n        return invalid_header_result\n\n    trace_id = _int_from_hex_str(trace_id_str, trace.INVALID_TRACE_ID)\n    span_id = _int_from_hex_str(span_id_str, trace.INVALID_SPAN_ID)\n    return trace_id, span_id, flags\n\n\ndef _int_from_hex_str(\n    identifier: str, default: typing.Optional[int]\n) -> typing.Optional[int]:\n    try:\n        return int(identifier, 16)\n    except ValueError:\n        return default\n", "path": "propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py"}], "after_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport typing\nimport urllib.parse\n\nfrom opentelemetry import baggage, trace\nfrom opentelemetry.context import Context\nfrom opentelemetry.propagators.textmap import (\n    CarrierT,\n    Getter,\n    Setter,\n    TextMapPropagator,\n    default_getter,\n    default_setter,\n)\nfrom opentelemetry.trace import format_span_id, format_trace_id\n\n\nclass JaegerPropagator(TextMapPropagator):\n    \"\"\"Propagator for the Jaeger format.\n\n    See: https://www.jaegertracing.io/docs/1.19/client-libraries/#propagation-format\n    \"\"\"\n\n    TRACE_ID_KEY = \"uber-trace-id\"\n    BAGGAGE_PREFIX = \"uberctx-\"\n    DEBUG_FLAG = 0x02\n\n    def extract(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        getter: Getter = default_getter,\n    ) -> Context:\n\n        if context is None:\n            context = Context()\n        header = getter.get(carrier, self.TRACE_ID_KEY)\n        if not header:\n            return context\n\n        context = self._extract_baggage(getter, carrier, context)\n\n        trace_id, span_id, flags = _parse_trace_id_header(header)\n        if (\n            trace_id == trace.INVALID_TRACE_ID\n            or span_id == trace.INVALID_SPAN_ID\n        ):\n            return context\n\n        span = trace.NonRecordingSpan(\n            trace.SpanContext(\n                trace_id=trace_id,\n                span_id=span_id,\n                is_remote=True,\n                trace_flags=trace.TraceFlags(flags & trace.TraceFlags.SAMPLED),\n            )\n        )\n        return trace.set_span_in_context(span, context)\n\n    def inject(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        setter: Setter = default_setter,\n    ) -> None:\n        span = trace.get_current_span(context=context)\n        span_context = span.get_span_context()\n        if span_context == trace.INVALID_SPAN_CONTEXT:\n            return\n\n        # Non-recording spans do not have a parent\n        span_parent_id = (\n            span.parent.span_id if span.is_recording() and span.parent else 0\n        )\n        trace_flags = span_context.trace_flags\n        if trace_flags.sampled:\n            trace_flags |= self.DEBUG_FLAG\n\n        # set span identity\n        setter.set(\n            carrier,\n            self.TRACE_ID_KEY,\n            _format_uber_trace_id(\n                span_context.trace_id,\n                span_context.span_id,\n                span_parent_id,\n                trace_flags,\n            ),\n        )\n\n        # set span baggage, if any\n        baggage_entries = baggage.get_all(context=context)\n        if not baggage_entries:\n            return\n        for key, value in baggage_entries.items():\n            baggage_key = self.BAGGAGE_PREFIX + key\n            setter.set(carrier, baggage_key, urllib.parse.quote(str(value)))\n\n    @property\n    def fields(self) -> typing.Set[str]:\n        return {self.TRACE_ID_KEY}\n\n    def _extract_baggage(self, getter, carrier, context):\n        baggage_keys = [\n            key\n            for key in getter.keys(carrier)\n            if key.startswith(self.BAGGAGE_PREFIX)\n        ]\n        for key in baggage_keys:\n            value = _extract_first_element(getter.get(carrier, key))\n            context = baggage.set_baggage(\n                key.replace(self.BAGGAGE_PREFIX, \"\"),\n                urllib.parse.unquote(value).strip(),\n                context=context,\n            )\n        return context\n\n\ndef _format_uber_trace_id(trace_id, span_id, parent_span_id, flags):\n    return f\"{format_trace_id(trace_id)}:{format_span_id(span_id)}:{format_span_id(parent_span_id)}:{flags:02x}\"\n\n\ndef _extract_first_element(\n    items: typing.Iterable[CarrierT],\n) -> typing.Optional[CarrierT]:\n    if items is None:\n        return None\n    return next(iter(items), None)\n\n\ndef _parse_trace_id_header(\n    items: typing.Iterable[CarrierT],\n) -> typing.Tuple[int]:\n    invalid_header_result = (trace.INVALID_TRACE_ID, trace.INVALID_SPAN_ID, 0)\n\n    header = _extract_first_element(items)\n    if header is None:\n        return invalid_header_result\n\n    fields = header.split(\":\")\n    if len(fields) != 4:\n        return invalid_header_result\n\n    trace_id_str, span_id_str, _parent_id_str, flags_str = fields\n    flags = _int_from_hex_str(flags_str, None)\n    if flags is None:\n        return invalid_header_result\n\n    trace_id = _int_from_hex_str(trace_id_str, trace.INVALID_TRACE_ID)\n    span_id = _int_from_hex_str(span_id_str, trace.INVALID_SPAN_ID)\n    return trace_id, span_id, flags\n\n\ndef _int_from_hex_str(\n    identifier: str, default: typing.Optional[int]\n) -> typing.Optional[int]:\n    try:\n        return int(identifier, 16)\n    except ValueError:\n        return default\n", "path": "propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py"}]}