We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add is_remote_parent span flags to OTLP exported Spans and SpanLinks
**Is your feature request related to a problem?**

After updating protobuf schema to 1.2.0 in 1164ab6c0193f658712b55469ecafbf031badc3b we can set the is_remote_parent flag when exporting spans and span links with OTLP. 

**Describe the solution you'd like**

Update OTLP exporter to fill the relevant bits in SpanFlags.

**Describe alternatives you've considered**

none

**Additional context**

Proto schema PR: https://github.com/open-telemetry/opentelemetry-proto/pull/484
Go implementation: https://github.com/open-telemetry/opentelemetry-go/pull/5194/files

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__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 logging
16 from collections import defaultdict
17 from typing import List, Optional, Sequence
18 
19 from opentelemetry.exporter.otlp.proto.common._internal import (
20     _encode_trace_id,
21     _encode_span_id,
22     _encode_instrumentation_scope,
23     _encode_attributes,
24     _encode_resource,
25 )
26 from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
27     ExportTraceServiceRequest as PB2ExportTraceServiceRequest,
28 )
29 from opentelemetry.proto.trace.v1.trace_pb2 import (
30     ScopeSpans as PB2ScopeSpans,
31 )
32 from opentelemetry.proto.trace.v1.trace_pb2 import (
33     ResourceSpans as PB2ResourceSpans,
34 )
35 from opentelemetry.proto.trace.v1.trace_pb2 import Span as PB2SPan
36 from opentelemetry.proto.trace.v1.trace_pb2 import Status as PB2Status
37 from opentelemetry.sdk.trace import Event, ReadableSpan
38 from opentelemetry.trace import Link
39 from opentelemetry.trace import SpanKind
40 from opentelemetry.trace.span import SpanContext, TraceState, Status
41 
42 # pylint: disable=E1101
43 _SPAN_KIND_MAP = {
44     SpanKind.INTERNAL: PB2SPan.SpanKind.SPAN_KIND_INTERNAL,
45     SpanKind.SERVER: PB2SPan.SpanKind.SPAN_KIND_SERVER,
46     SpanKind.CLIENT: PB2SPan.SpanKind.SPAN_KIND_CLIENT,
47     SpanKind.PRODUCER: PB2SPan.SpanKind.SPAN_KIND_PRODUCER,
48     SpanKind.CONSUMER: PB2SPan.SpanKind.SPAN_KIND_CONSUMER,
49 }
50 
51 _logger = logging.getLogger(__name__)
52 
53 
54 def encode_spans(
55     sdk_spans: Sequence[ReadableSpan],
56 ) -> PB2ExportTraceServiceRequest:
57     return PB2ExportTraceServiceRequest(
58         resource_spans=_encode_resource_spans(sdk_spans)
59     )
60 
61 
62 def _encode_resource_spans(
63     sdk_spans: Sequence[ReadableSpan],
64 ) -> List[PB2ResourceSpans]:
65     # We need to inspect the spans and group + structure them as:
66     #
67     #   Resource
68     #     Instrumentation Library
69     #       Spans
70     #
71     # First loop organizes the SDK spans in this structure. Protobuf messages
72     # are not hashable so we stick with SDK data in this phase.
73     #
74     # Second loop encodes the data into Protobuf format.
75     #
76     sdk_resource_spans = defaultdict(lambda: defaultdict(list))
77 
78     for sdk_span in sdk_spans:
79         sdk_resource = sdk_span.resource
80         sdk_instrumentation = sdk_span.instrumentation_scope or None
81         pb2_span = _encode_span(sdk_span)
82 
83         sdk_resource_spans[sdk_resource][sdk_instrumentation].append(pb2_span)
84 
85     pb2_resource_spans = []
86 
87     for sdk_resource, sdk_instrumentations in sdk_resource_spans.items():
88         scope_spans = []
89         for sdk_instrumentation, pb2_spans in sdk_instrumentations.items():
90             scope_spans.append(
91                 PB2ScopeSpans(
92                     scope=(_encode_instrumentation_scope(sdk_instrumentation)),
93                     spans=pb2_spans,
94                 )
95             )
96         pb2_resource_spans.append(
97             PB2ResourceSpans(
98                 resource=_encode_resource(sdk_resource),
99                 scope_spans=scope_spans,
100                 schema_url=sdk_resource.schema_url,
101             )
102         )
103 
104     return pb2_resource_spans
105 
106 
107 def _encode_span(sdk_span: ReadableSpan) -> PB2SPan:
108     span_context = sdk_span.get_span_context()
109     return PB2SPan(
110         trace_id=_encode_trace_id(span_context.trace_id),
111         span_id=_encode_span_id(span_context.span_id),
112         trace_state=_encode_trace_state(span_context.trace_state),
113         parent_span_id=_encode_parent_id(sdk_span.parent),
114         name=sdk_span.name,
115         kind=_SPAN_KIND_MAP[sdk_span.kind],
116         start_time_unix_nano=sdk_span.start_time,
117         end_time_unix_nano=sdk_span.end_time,
118         attributes=_encode_attributes(sdk_span.attributes),
119         events=_encode_events(sdk_span.events),
120         links=_encode_links(sdk_span.links),
121         status=_encode_status(sdk_span.status),
122         dropped_attributes_count=sdk_span.dropped_attributes,
123         dropped_events_count=sdk_span.dropped_events,
124         dropped_links_count=sdk_span.dropped_links,
125     )
126 
127 
128 def _encode_events(
129     events: Sequence[Event],
130 ) -> Optional[List[PB2SPan.Event]]:
131     pb2_events = None
132     if events:
133         pb2_events = []
134         for event in events:
135             encoded_event = PB2SPan.Event(
136                 name=event.name,
137                 time_unix_nano=event.timestamp,
138                 attributes=_encode_attributes(event.attributes),
139                 dropped_attributes_count=event.attributes.dropped,
140             )
141             pb2_events.append(encoded_event)
142     return pb2_events
143 
144 
145 def _encode_links(links: Sequence[Link]) -> Sequence[PB2SPan.Link]:
146     pb2_links = None
147     if links:
148         pb2_links = []
149         for link in links:
150             encoded_link = PB2SPan.Link(
151                 trace_id=_encode_trace_id(link.context.trace_id),
152                 span_id=_encode_span_id(link.context.span_id),
153                 attributes=_encode_attributes(link.attributes),
154                 dropped_attributes_count=link.attributes.dropped,
155             )
156             pb2_links.append(encoded_link)
157     return pb2_links
158 
159 
160 def _encode_status(status: Status) -> Optional[PB2Status]:
161     pb2_status = None
162     if status is not None:
163         pb2_status = PB2Status(
164             code=status.status_code.value,
165             message=status.description,
166         )
167     return pb2_status
168 
169 
170 def _encode_trace_state(trace_state: TraceState) -> Optional[str]:
171     pb2_trace_state = None
172     if trace_state is not None:
173         pb2_trace_state = ",".join(
174             [f"{key}={value}" for key, value in (trace_state.items())]
175         )
176     return pb2_trace_state
177 
178 
179 def _encode_parent_id(context: Optional[SpanContext]) -> Optional[bytes]:
180     if context:
181         return _encode_span_id(context.span_id)
182     return None
183
```
--- 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/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py
--- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py
+++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py
@@ -17,27 +17,25 @@
 from typing import List, Optional, Sequence
 
 from opentelemetry.exporter.otlp.proto.common._internal import (
-    _encode_trace_id,
-    _encode_span_id,
-    _encode_instrumentation_scope,
     _encode_attributes,
+    _encode_instrumentation_scope,
     _encode_resource,
+    _encode_span_id,
+    _encode_trace_id,
 )
 from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
     ExportTraceServiceRequest as PB2ExportTraceServiceRequest,
 )
-from opentelemetry.proto.trace.v1.trace_pb2 import (
-    ScopeSpans as PB2ScopeSpans,
-)
 from opentelemetry.proto.trace.v1.trace_pb2 import (
     ResourceSpans as PB2ResourceSpans,
 )
+from opentelemetry.proto.trace.v1.trace_pb2 import ScopeSpans as PB2ScopeSpans
 from opentelemetry.proto.trace.v1.trace_pb2 import Span as PB2SPan
+from opentelemetry.proto.trace.v1.trace_pb2 import SpanFlags as PB2SpanFlags
 from opentelemetry.proto.trace.v1.trace_pb2 import Status as PB2Status
 from opentelemetry.sdk.trace import Event, ReadableSpan
-from opentelemetry.trace import Link
-from opentelemetry.trace import SpanKind
-from opentelemetry.trace.span import SpanContext, TraceState, Status
+from opentelemetry.trace import Link, SpanKind
+from opentelemetry.trace.span import SpanContext, Status, TraceState
 
 # pylint: disable=E1101
 _SPAN_KIND_MAP = {
@@ -104,6 +102,13 @@
     return pb2_resource_spans
 
 
+def _span_flags(parent_span_context: Optional[SpanContext]) -> int:
+    flags = PB2SpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
+    if parent_span_context and parent_span_context.is_remote:
+        flags |= PB2SpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
+    return flags
+
+
 def _encode_span(sdk_span: ReadableSpan) -> PB2SPan:
     span_context = sdk_span.get_span_context()
     return PB2SPan(
@@ -122,6 +127,7 @@
         dropped_attributes_count=sdk_span.dropped_attributes,
         dropped_events_count=sdk_span.dropped_events,
         dropped_links_count=sdk_span.dropped_links,
+        flags=_span_flags(sdk_span.parent),
     )
 
 
@@ -152,6 +158,7 @@
                 span_id=_encode_span_id(link.context.span_id),
                 attributes=_encode_attributes(link.attributes),
                 dropped_attributes_count=link.attributes.dropped,
+                flags=_span_flags(link.context),
             )
             pb2_links.append(encoded_link)
     return pb2_links

{"golden_diff": "diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py\n--- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py\n+++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py\n@@ -17,27 +17,25 @@\n from typing import List, Optional, Sequence\n \n from opentelemetry.exporter.otlp.proto.common._internal import (\n-    _encode_trace_id,\n-    _encode_span_id,\n-    _encode_instrumentation_scope,\n     _encode_attributes,\n+    _encode_instrumentation_scope,\n     _encode_resource,\n+    _encode_span_id,\n+    _encode_trace_id,\n )\n from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (\n     ExportTraceServiceRequest as PB2ExportTraceServiceRequest,\n )\n-from opentelemetry.proto.trace.v1.trace_pb2 import (\n-    ScopeSpans as PB2ScopeSpans,\n-)\n from opentelemetry.proto.trace.v1.trace_pb2 import (\n     ResourceSpans as PB2ResourceSpans,\n )\n+from opentelemetry.proto.trace.v1.trace_pb2 import ScopeSpans as PB2ScopeSpans\n from opentelemetry.proto.trace.v1.trace_pb2 import Span as PB2SPan\n+from opentelemetry.proto.trace.v1.trace_pb2 import SpanFlags as PB2SpanFlags\n from opentelemetry.proto.trace.v1.trace_pb2 import Status as PB2Status\n from opentelemetry.sdk.trace import Event, ReadableSpan\n-from opentelemetry.trace import Link\n-from opentelemetry.trace import SpanKind\n-from opentelemetry.trace.span import SpanContext, TraceState, Status\n+from opentelemetry.trace import Link, SpanKind\n+from opentelemetry.trace.span import SpanContext, Status, TraceState\n \n # pylint: disable=E1101\n _SPAN_KIND_MAP = {\n@@ -104,6 +102,13 @@\n     return pb2_resource_spans\n \n \n+def _span_flags(parent_span_context: Optional[SpanContext]) -> int:\n+    flags = PB2SpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK\n+    if parent_span_context and parent_span_context.is_remote:\n+        flags |= PB2SpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK\n+    return flags\n+\n+\n def _encode_span(sdk_span: ReadableSpan) -> PB2SPan:\n     span_context = sdk_span.get_span_context()\n     return PB2SPan(\n@@ -122,6 +127,7 @@\n         dropped_attributes_count=sdk_span.dropped_attributes,\n         dropped_events_count=sdk_span.dropped_events,\n         dropped_links_count=sdk_span.dropped_links,\n+        flags=_span_flags(sdk_span.parent),\n     )\n \n \n@@ -152,6 +158,7 @@\n                 span_id=_encode_span_id(link.context.span_id),\n                 attributes=_encode_attributes(link.attributes),\n                 dropped_attributes_count=link.attributes.dropped,\n+                flags=_span_flags(link.context),\n             )\n             pb2_links.append(encoded_link)\n     return pb2_links\n", "issue": "Add is_remote_parent span flags to OTLP exported Spans and SpanLinks\n**Is your feature request related to a problem?**\r\n\r\nAfter updating protobuf schema to 1.2.0 in 1164ab6c0193f658712b55469ecafbf031badc3b we can set the is_remote_parent flag when exporting spans and span links with OTLP. \r\n\r\n**Describe the solution you'd like**\r\n\r\nUpdate OTLP exporter to fill the relevant bits in SpanFlags.\r\n\r\n**Describe alternatives you've considered**\r\n\r\nnone\r\n\r\n**Additional context**\r\n\r\nProto schema PR: https://github.com/open-telemetry/opentelemetry-proto/pull/484\r\nGo implementation: https://github.com/open-telemetry/opentelemetry-go/pull/5194/files\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 logging\nfrom collections import defaultdict\nfrom typing import List, Optional, Sequence\n\nfrom opentelemetry.exporter.otlp.proto.common._internal import (\n    _encode_trace_id,\n    _encode_span_id,\n    _encode_instrumentation_scope,\n    _encode_attributes,\n    _encode_resource,\n)\nfrom opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (\n    ExportTraceServiceRequest as PB2ExportTraceServiceRequest,\n)\nfrom opentelemetry.proto.trace.v1.trace_pb2 import (\n    ScopeSpans as PB2ScopeSpans,\n)\nfrom opentelemetry.proto.trace.v1.trace_pb2 import (\n    ResourceSpans as PB2ResourceSpans,\n)\nfrom opentelemetry.proto.trace.v1.trace_pb2 import Span as PB2SPan\nfrom opentelemetry.proto.trace.v1.trace_pb2 import Status as PB2Status\nfrom opentelemetry.sdk.trace import Event, ReadableSpan\nfrom opentelemetry.trace import Link\nfrom opentelemetry.trace import SpanKind\nfrom opentelemetry.trace.span import SpanContext, TraceState, Status\n\n# pylint: disable=E1101\n_SPAN_KIND_MAP = {\n    SpanKind.INTERNAL: PB2SPan.SpanKind.SPAN_KIND_INTERNAL,\n    SpanKind.SERVER: PB2SPan.SpanKind.SPAN_KIND_SERVER,\n    SpanKind.CLIENT: PB2SPan.SpanKind.SPAN_KIND_CLIENT,\n    SpanKind.PRODUCER: PB2SPan.SpanKind.SPAN_KIND_PRODUCER,\n    SpanKind.CONSUMER: PB2SPan.SpanKind.SPAN_KIND_CONSUMER,\n}\n\n_logger = logging.getLogger(__name__)\n\n\ndef encode_spans(\n    sdk_spans: Sequence[ReadableSpan],\n) -> PB2ExportTraceServiceRequest:\n    return PB2ExportTraceServiceRequest(\n        resource_spans=_encode_resource_spans(sdk_spans)\n    )\n\n\ndef _encode_resource_spans(\n    sdk_spans: Sequence[ReadableSpan],\n) -> List[PB2ResourceSpans]:\n    # We need to inspect the spans and group + structure them as:\n    #\n    #   Resource\n    #     Instrumentation Library\n    #       Spans\n    #\n    # First loop organizes the SDK spans in this structure. Protobuf messages\n    # are not hashable so we stick with SDK data in this phase.\n    #\n    # Second loop encodes the data into Protobuf format.\n    #\n    sdk_resource_spans = defaultdict(lambda: defaultdict(list))\n\n    for sdk_span in sdk_spans:\n        sdk_resource = sdk_span.resource\n        sdk_instrumentation = sdk_span.instrumentation_scope or None\n        pb2_span = _encode_span(sdk_span)\n\n        sdk_resource_spans[sdk_resource][sdk_instrumentation].append(pb2_span)\n\n    pb2_resource_spans = []\n\n    for sdk_resource, sdk_instrumentations in sdk_resource_spans.items():\n        scope_spans = []\n        for sdk_instrumentation, pb2_spans in sdk_instrumentations.items():\n            scope_spans.append(\n                PB2ScopeSpans(\n                    scope=(_encode_instrumentation_scope(sdk_instrumentation)),\n                    spans=pb2_spans,\n                )\n            )\n        pb2_resource_spans.append(\n            PB2ResourceSpans(\n                resource=_encode_resource(sdk_resource),\n                scope_spans=scope_spans,\n                schema_url=sdk_resource.schema_url,\n            )\n        )\n\n    return pb2_resource_spans\n\n\ndef _encode_span(sdk_span: ReadableSpan) -> PB2SPan:\n    span_context = sdk_span.get_span_context()\n    return PB2SPan(\n        trace_id=_encode_trace_id(span_context.trace_id),\n        span_id=_encode_span_id(span_context.span_id),\n        trace_state=_encode_trace_state(span_context.trace_state),\n        parent_span_id=_encode_parent_id(sdk_span.parent),\n        name=sdk_span.name,\n        kind=_SPAN_KIND_MAP[sdk_span.kind],\n        start_time_unix_nano=sdk_span.start_time,\n        end_time_unix_nano=sdk_span.end_time,\n        attributes=_encode_attributes(sdk_span.attributes),\n        events=_encode_events(sdk_span.events),\n        links=_encode_links(sdk_span.links),\n        status=_encode_status(sdk_span.status),\n        dropped_attributes_count=sdk_span.dropped_attributes,\n        dropped_events_count=sdk_span.dropped_events,\n        dropped_links_count=sdk_span.dropped_links,\n    )\n\n\ndef _encode_events(\n    events: Sequence[Event],\n) -> Optional[List[PB2SPan.Event]]:\n    pb2_events = None\n    if events:\n        pb2_events = []\n        for event in events:\n            encoded_event = PB2SPan.Event(\n                name=event.name,\n                time_unix_nano=event.timestamp,\n                attributes=_encode_attributes(event.attributes),\n                dropped_attributes_count=event.attributes.dropped,\n            )\n            pb2_events.append(encoded_event)\n    return pb2_events\n\n\ndef _encode_links(links: Sequence[Link]) -> Sequence[PB2SPan.Link]:\n    pb2_links = None\n    if links:\n        pb2_links = []\n        for link in links:\n            encoded_link = PB2SPan.Link(\n                trace_id=_encode_trace_id(link.context.trace_id),\n                span_id=_encode_span_id(link.context.span_id),\n                attributes=_encode_attributes(link.attributes),\n                dropped_attributes_count=link.attributes.dropped,\n            )\n            pb2_links.append(encoded_link)\n    return pb2_links\n\n\ndef _encode_status(status: Status) -> Optional[PB2Status]:\n    pb2_status = None\n    if status is not None:\n        pb2_status = PB2Status(\n            code=status.status_code.value,\n            message=status.description,\n        )\n    return pb2_status\n\n\ndef _encode_trace_state(trace_state: TraceState) -> Optional[str]:\n    pb2_trace_state = None\n    if trace_state is not None:\n        pb2_trace_state = \",\".join(\n            [f\"{key}={value}\" for key, value in (trace_state.items())]\n        )\n    return pb2_trace_state\n\n\ndef _encode_parent_id(context: Optional[SpanContext]) -> Optional[bytes]:\n    if context:\n        return _encode_span_id(context.span_id)\n    return None\n", "path": "exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__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 logging\nfrom collections import defaultdict\nfrom typing import List, Optional, Sequence\n\nfrom opentelemetry.exporter.otlp.proto.common._internal import (\n    _encode_attributes,\n    _encode_instrumentation_scope,\n    _encode_resource,\n    _encode_span_id,\n    _encode_trace_id,\n)\nfrom opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (\n    ExportTraceServiceRequest as PB2ExportTraceServiceRequest,\n)\nfrom opentelemetry.proto.trace.v1.trace_pb2 import (\n    ResourceSpans as PB2ResourceSpans,\n)\nfrom opentelemetry.proto.trace.v1.trace_pb2 import ScopeSpans as PB2ScopeSpans\nfrom opentelemetry.proto.trace.v1.trace_pb2 import Span as PB2SPan\nfrom opentelemetry.proto.trace.v1.trace_pb2 import SpanFlags as PB2SpanFlags\nfrom opentelemetry.proto.trace.v1.trace_pb2 import Status as PB2Status\nfrom opentelemetry.sdk.trace import Event, ReadableSpan\nfrom opentelemetry.trace import Link, SpanKind\nfrom opentelemetry.trace.span import SpanContext, Status, TraceState\n\n# pylint: disable=E1101\n_SPAN_KIND_MAP = {\n    SpanKind.INTERNAL: PB2SPan.SpanKind.SPAN_KIND_INTERNAL,\n    SpanKind.SERVER: PB2SPan.SpanKind.SPAN_KIND_SERVER,\n    SpanKind.CLIENT: PB2SPan.SpanKind.SPAN_KIND_CLIENT,\n    SpanKind.PRODUCER: PB2SPan.SpanKind.SPAN_KIND_PRODUCER,\n    SpanKind.CONSUMER: PB2SPan.SpanKind.SPAN_KIND_CONSUMER,\n}\n\n_logger = logging.getLogger(__name__)\n\n\ndef encode_spans(\n    sdk_spans: Sequence[ReadableSpan],\n) -> PB2ExportTraceServiceRequest:\n    return PB2ExportTraceServiceRequest(\n        resource_spans=_encode_resource_spans(sdk_spans)\n    )\n\n\ndef _encode_resource_spans(\n    sdk_spans: Sequence[ReadableSpan],\n) -> List[PB2ResourceSpans]:\n    # We need to inspect the spans and group + structure them as:\n    #\n    #   Resource\n    #     Instrumentation Library\n    #       Spans\n    #\n    # First loop organizes the SDK spans in this structure. Protobuf messages\n    # are not hashable so we stick with SDK data in this phase.\n    #\n    # Second loop encodes the data into Protobuf format.\n    #\n    sdk_resource_spans = defaultdict(lambda: defaultdict(list))\n\n    for sdk_span in sdk_spans:\n        sdk_resource = sdk_span.resource\n        sdk_instrumentation = sdk_span.instrumentation_scope or None\n        pb2_span = _encode_span(sdk_span)\n\n        sdk_resource_spans[sdk_resource][sdk_instrumentation].append(pb2_span)\n\n    pb2_resource_spans = []\n\n    for sdk_resource, sdk_instrumentations in sdk_resource_spans.items():\n        scope_spans = []\n        for sdk_instrumentation, pb2_spans in sdk_instrumentations.items():\n            scope_spans.append(\n                PB2ScopeSpans(\n                    scope=(_encode_instrumentation_scope(sdk_instrumentation)),\n                    spans=pb2_spans,\n                )\n            )\n        pb2_resource_spans.append(\n            PB2ResourceSpans(\n                resource=_encode_resource(sdk_resource),\n                scope_spans=scope_spans,\n                schema_url=sdk_resource.schema_url,\n            )\n        )\n\n    return pb2_resource_spans\n\n\ndef _span_flags(parent_span_context: Optional[SpanContext]) -> int:\n    flags = PB2SpanFlags.SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK\n    if parent_span_context and parent_span_context.is_remote:\n        flags |= PB2SpanFlags.SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK\n    return flags\n\n\ndef _encode_span(sdk_span: ReadableSpan) -> PB2SPan:\n    span_context = sdk_span.get_span_context()\n    return PB2SPan(\n        trace_id=_encode_trace_id(span_context.trace_id),\n        span_id=_encode_span_id(span_context.span_id),\n        trace_state=_encode_trace_state(span_context.trace_state),\n        parent_span_id=_encode_parent_id(sdk_span.parent),\n        name=sdk_span.name,\n        kind=_SPAN_KIND_MAP[sdk_span.kind],\n        start_time_unix_nano=sdk_span.start_time,\n        end_time_unix_nano=sdk_span.end_time,\n        attributes=_encode_attributes(sdk_span.attributes),\n        events=_encode_events(sdk_span.events),\n        links=_encode_links(sdk_span.links),\n        status=_encode_status(sdk_span.status),\n        dropped_attributes_count=sdk_span.dropped_attributes,\n        dropped_events_count=sdk_span.dropped_events,\n        dropped_links_count=sdk_span.dropped_links,\n        flags=_span_flags(sdk_span.parent),\n    )\n\n\ndef _encode_events(\n    events: Sequence[Event],\n) -> Optional[List[PB2SPan.Event]]:\n    pb2_events = None\n    if events:\n        pb2_events = []\n        for event in events:\n            encoded_event = PB2SPan.Event(\n                name=event.name,\n                time_unix_nano=event.timestamp,\n                attributes=_encode_attributes(event.attributes),\n                dropped_attributes_count=event.attributes.dropped,\n            )\n            pb2_events.append(encoded_event)\n    return pb2_events\n\n\ndef _encode_links(links: Sequence[Link]) -> Sequence[PB2SPan.Link]:\n    pb2_links = None\n    if links:\n        pb2_links = []\n        for link in links:\n            encoded_link = PB2SPan.Link(\n                trace_id=_encode_trace_id(link.context.trace_id),\n                span_id=_encode_span_id(link.context.span_id),\n                attributes=_encode_attributes(link.attributes),\n                dropped_attributes_count=link.attributes.dropped,\n                flags=_span_flags(link.context),\n            )\n            pb2_links.append(encoded_link)\n    return pb2_links\n\n\ndef _encode_status(status: Status) -> Optional[PB2Status]:\n    pb2_status = None\n    if status is not None:\n        pb2_status = PB2Status(\n            code=status.status_code.value,\n            message=status.description,\n        )\n    return pb2_status\n\n\ndef _encode_trace_state(trace_state: TraceState) -> Optional[str]:\n    pb2_trace_state = None\n    if trace_state is not None:\n        pb2_trace_state = \",\".join(\n            [f\"{key}={value}\" for key, value in (trace_state.items())]\n        )\n    return pb2_trace_state\n\n\ndef _encode_parent_id(context: Optional[SpanContext]) -> Optional[bytes]:\n    if context:\n        return _encode_span_id(context.span_id)\n    return None\n", "path": "exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py"}]}