Repository: open-telemetry/opentelemetry-python

Issue:
Jaeger gRPC exporter lacking span parent structure
**Describe your environment**
I'm running opentelemetry in a docker container on my local computer.
```
root@ea1e70b65e3c:/log# python3 --version
Python 3.7.3
root@ea1e70b65e3c:/log# 
(pyvenv) root@ea1e70b65e3c:/var/opt/ncs/packages/opentelemetry-exporter# python3
Python 3.7.3 (default, Jan 22 2021, 20:04:44) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import opentelemetry.version
>>> opentelemetry.version.__version__
'1.1.0'
>>> 
```


**Steps to reproduce**
I have an application that is using the OpenTelemetry library and is exporting data just fine to Jaeger via the Thrift interface. I would need to export data over IPv6 though and the Thrift over UDP is hard coded to IPv4 (see #1559), thus I'm trying to use gRPC. I have succeeded in getting data exported but the data is lacking the parent/child structure.

Reading https://github.com/open-telemetry/opentelemetry-python/blob/main/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/translate/__init__.py, I don't see that it is really reading out the parent structure and exporting. Am I missing something or is it just missing?

In the Thrift model, there is a parentSpanId. In gRPC it seems to be modeled differently, like there's a list of references that can be of the type `CHILD_OF` or `FOLLOWS_FROM`. It is set here https://github.com/open-telemetry/opentelemetry-python/blob/main/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/translate/__init__.py#L254 and extracted using https://github.com/open-telemetry/opentelemetry-python/blob/main/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/translate/__init__.py#L318 but it only looks at the span links, not at the normal span parent relation.

**What is the expected behavior?**
Seeing child spans of parents etc. A nested structure.

**What is the actual behavior?**
A flat list of spans.

**Additional context**




Discussion:

Resolving patch:
diff --git a/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/translate/__init__.py b/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/translate/__init__.py
--- a/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/translate/__init__.py
+++ b/exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/translate/__init__.py
@@ -318,10 +318,18 @@ def _extract_tags(
     def _extract_refs(
         self, span: ReadableSpan
     ) -> Optional[Sequence[model_pb2.SpanRef]]:
-        if not span.links:
-            return None
 
         refs = []
+        if span.parent:
+            ctx = span.get_span_context()
+            parent_id = span.parent.span_id
+            parent_ref = model_pb2.SpanRef(
+                ref_type=model_pb2.SpanRefType.CHILD_OF,
+                trace_id=_trace_id_to_bytes(ctx.trace_id),
+                span_id=_span_id_to_bytes(parent_id),
+            )
+            refs.append(parent_ref)
+
         for link in span.links:
             trace_id = link.context.trace_id
             span_id = link.context.span_id


Test patch:
diff --git a/exporter/opentelemetry-exporter-jaeger-proto-grpc/tests/test_jaeger_exporter_protobuf.py b/exporter/opentelemetry-exporter-jaeger-proto-grpc/tests/test_jaeger_exporter_protobuf.py
--- a/exporter/opentelemetry-exporter-jaeger-proto-grpc/tests/test_jaeger_exporter_protobuf.py
+++ b/exporter/opentelemetry-exporter-jaeger-proto-grpc/tests/test_jaeger_exporter_protobuf.py
@@ -287,11 +287,16 @@ def test_translate_to_jaeger(self):
                     ),
                 ],
                 references=[
+                    model_pb2.SpanRef(
+                        ref_type=model_pb2.SpanRefType.CHILD_OF,
+                        trace_id=pb_translator._trace_id_to_bytes(trace_id),
+                        span_id=pb_translator._span_id_to_bytes(parent_id),
+                    ),
                     model_pb2.SpanRef(
                         ref_type=model_pb2.SpanRefType.FOLLOWS_FROM,
                         trace_id=pb_translator._trace_id_to_bytes(trace_id),
                         span_id=pb_translator._span_id_to_bytes(other_id),
-                    )
+                    ),
                 ],
                 logs=[
                     model_pb2.Log(