Repository: open-telemetry/opentelemetry-python

Issue:
inconsistency printing to json from ConsoleSpanExporter
Running the following code:
```
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    ConsoleSpanExporter,
    SimpleSpanProcessor,
)

trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
    SimpleSpanProcessor(ConsoleSpanExporter())
)
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("foo"):
    with tracer.start_as_current_span("bar"):
        print("Hello world!")
```

outputs the following span information, note the parent ID formatting is inconsistent:
```
Hello world!
{
    "name": "bar",
    "context": {
        "trace_id": "0xaba880c3256d04f47bcdecf9bf3ba84e",
        "span_id": "0x3014b62ab356f774",
        "trace_state": "[]"
    },
    "kind": "SpanKind.INTERNAL",
    "parent_id": "53321c6000aabdfe",
    "start_time": "2021-05-10T15:21:55.215847Z",
    "end_time": "2021-05-10T15:21:55.215898Z",
    "status": {
        "status_code": "UNSET"
    },
    "attributes": {},
    "events": [],
    "links": [],
    "resource": {
        "telemetry.sdk.language": "python",
        "telemetry.sdk.name": "opentelemetry",
        "telemetry.sdk.version": "1.2.0.dev0",
        "service.name": "unknown_service"
    }
}
{
    "name": "foo",
    "context": {
        "trace_id": "0xaba880c3256d04f47bcdecf9bf3ba84e",
        "span_id": "0x53321c6000aabdfe",
        "trace_state": "[]"
    },
    "kind": "SpanKind.INTERNAL",
    "parent_id": null,
    "start_time": "2021-05-10T15:21:55.215765Z",
    "end_time": "2021-05-10T15:21:55.216855Z",
    "status": {
        "status_code": "UNSET"
    },
    "attributes": {},
    "events": [],
    "links": [],
    "resource": {
        "telemetry.sdk.language": "python",
        "telemetry.sdk.name": "opentelemetry",
        "telemetry.sdk.version": "1.2.0.dev0",
        "service.name": "unknown_service"
    }
}
```



Discussion:

Resolving patch:
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
--- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
@@ -483,9 +483,13 @@ def to_json(self, indent=4):
         if self.parent is not None:
             if isinstance(self.parent, Span):
                 ctx = self.parent.context
-                parent_id = trace_api.format_span_id(ctx.span_id)
+                parent_id = "0x{}".format(
+                    trace_api.format_span_id(ctx.span_id)
+                )
             elif isinstance(self.parent, SpanContext):
-                parent_id = trace_api.format_span_id(self.parent.span_id)
+                parent_id = "0x{}".format(
+                    trace_api.format_span_id(self.parent.span_id)
+                )
 
         start_time = None
         if self._start_time:


Test patch:
diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py
--- a/opentelemetry-sdk/tests/trace/test_trace.py
+++ b/opentelemetry-sdk/tests/trace/test_trace.py
@@ -1221,7 +1221,10 @@ def test_to_json(self):
             is_remote=False,
             trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED),
         )
-        span = trace._Span("span-name", context, resource=Resource({}))
+        parent = trace._Span("parent-name", context, resource=Resource({}))
+        span = trace._Span(
+            "span-name", context, resource=Resource({}), parent=parent
+        )
 
         self.assertEqual(
             span.to_json(),
@@ -1233,7 +1236,7 @@ def test_to_json(self):
         "trace_state": "[]"
     },
     "kind": "SpanKind.INTERNAL",
-    "parent_id": null,
+    "parent_id": "0x00000000deadbef0",
     "start_time": null,
     "end_time": null,
     "status": {
@@ -1247,7 +1250,7 @@ def test_to_json(self):
         )
         self.assertEqual(
             span.to_json(indent=None),
-            '{"name": "span-name", "context": {"trace_id": "0x000000000000000000000000deadbeef", "span_id": "0x00000000deadbef0", "trace_state": "[]"}, "kind": "SpanKind.INTERNAL", "parent_id": null, "start_time": null, "end_time": null, "status": {"status_code": "UNSET"}, "attributes": {}, "events": [], "links": [], "resource": {}}',
+            '{"name": "span-name", "context": {"trace_id": "0x000000000000000000000000deadbeef", "span_id": "0x00000000deadbef0", "trace_state": "[]"}, "kind": "SpanKind.INTERNAL", "parent_id": "0x00000000deadbef0", "start_time": null, "end_time": null, "status": {"status_code": "UNSET"}, "attributes": {}, "events": [], "links": [], "resource": {}}',
         )
 
     def test_attributes_to_json(self):