diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index 3e2cc02c337..87f4a097d50 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -14,6 +14,7 @@ import collections import logging +import sys import threading import typing from enum import Enum @@ -266,7 +267,15 @@ class ConsoleSpanExporter(SpanExporter): spans to the console STDOUT. """ + def __init__( + self, + out: typing.IO = sys.stdout, + formatter: typing.Callable[[Span], str] = str, + ): + self.out = out + self.formatter = formatter + def export(self, spans: typing.Sequence[Span]) -> SpanExportResult: for span in spans: - print(span) + self.out.write(self.formatter(span)) return SpanExportResult.SUCCESS diff --git a/opentelemetry-sdk/tests/trace/export/test_export.py b/opentelemetry-sdk/tests/trace/export/test_export.py index ea513a48589..e598b9680a9 100644 --- a/opentelemetry-sdk/tests/trace/export/test_export.py +++ b/opentelemetry-sdk/tests/trace/export/test_export.py @@ -276,3 +276,31 @@ def test_batch_span_processor_parameters(self): max_queue_size=256, max_export_batch_size=512, ) + + +class TestConsoleSpanExporter(unittest.TestCase): + def test_export(self): # pylint: disable=no-self-use + """Check that the console exporter prints spans.""" + exporter = export.ConsoleSpanExporter() + + # Mocking stdout interferes with debugging and test reporting, mock on + # the exporter instance instead. + span = trace.Span("span name", mock.Mock()) + with mock.patch.object(exporter, "out") as mock_stdout: + exporter.export([span]) + mock_stdout.write.assert_called_once_with(str(span)) + self.assertEqual(mock_stdout.write.call_count, 1) + + def test_export_custom(self): # pylint: disable=no-self-use + """Check that console exporter uses custom io, formatter.""" + mock_span_str = mock.Mock(str) + + def formatter(span): # pylint: disable=unused-argument + return mock_span_str + + mock_stdout = mock.Mock() + exporter = export.ConsoleSpanExporter( + out=mock_stdout, formatter=formatter + ) + exporter.export([trace.Span("span name", mock.Mock())]) + mock_stdout.write.assert_called_once_with(mock_span_str)