mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-28 12:43:39 +08:00
Add a rich console exporter (#686)
* Add a rich console exporter * be more lenient on missing parent spans * Apply suggestions from code review Co-authored-by: Aaron Abbott <aaronabbott@google.com> * run black over source * patch change by hand * update changelog * remove defunct statement * Clarify the simple/batch span processor * fix f-strings that dont have formatting * clarify span usage and update classifiers * make child_to_tree a private function and rename some variables Co-authored-by: Aaron Abbott <aaronabbott@google.com> Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com> Co-authored-by: alrex <aboten@lightstep.com>
This commit is contained in:
@ -12,10 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
- `opentelemetry-instrumentation-elasticsearch` Added `response_hook` and `request_hook` callbacks
|
||||
([#670](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/670))
|
||||
|
||||
### Added
|
||||
- `opentelemetry-instrumentation-redis` added request_hook and response_hook callbacks passed as arguments to the instrument method.
|
||||
([#669](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/669))
|
||||
- `opentelemetry-exporter-richconsole` Initial release
|
||||
([#686](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/686))
|
||||
|
||||
### Changed
|
||||
- `opentelemetry-instrumentation-botocore` Unpatch botocore Endpoint.prepare_request on uninstrument
|
||||
|
28
exporter/opentelemetry-exporter-richconsole/README.rst
Normal file
28
exporter/opentelemetry-exporter-richconsole/README.rst
Normal file
@ -0,0 +1,28 @@
|
||||
OpenTelemetry Rich Console Exporter
|
||||
===================================
|
||||
|
||||
|pypi|
|
||||
|
||||
.. |pypi| image:: https://badge.fury.io/py/opentelemetry-exporter-richconsole.svg
|
||||
:target: https://pypi.org/project/opentelemetry-exporter-richconsole/
|
||||
|
||||
This library is a console exporter using the Rich tree view. When used with a batch span processor, the rich console exporter will show the trace as a
|
||||
tree and all related spans as children within the tree, including properties.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
::
|
||||
|
||||
pip install opentelemetry-exporter-richconsole
|
||||
|
||||
|
||||
.. _Rich: https://rich.readthedocs.io/
|
||||
.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
* `Rich <https://rich.readthedocs.io/>`_
|
||||
* `OpenTelemetry Project <https://opentelemetry.io/>`_
|
51
exporter/opentelemetry-exporter-richconsole/setup.cfg
Normal file
51
exporter/opentelemetry-exporter-richconsole/setup.cfg
Normal file
@ -0,0 +1,51 @@
|
||||
# Copyright The OpenTelemetry Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
[metadata]
|
||||
name = opentelemetry-exporter-richconsole
|
||||
description = Rich Console Exporter for OpenTelemetry
|
||||
long_description = file: README.rst
|
||||
long_description_content_type = text/x-rst
|
||||
author = OpenTelemetry Authors
|
||||
author_email = cncf-opentelemetry-contributors@lists.cncf.io
|
||||
url = https://github.com/open-telemetry/opentelemetry-python-contrib/exporter/opentelemetry-exporter-richconsole
|
||||
platforms = any
|
||||
license = Apache-2.0
|
||||
classifiers =
|
||||
Development Status :: 4 - Beta
|
||||
Intended Audience :: Developers
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.6
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
Programming Language :: Python :: 3.9
|
||||
|
||||
[options]
|
||||
python_requires = >=3.6
|
||||
package_dir=
|
||||
=src
|
||||
packages=find_namespace:
|
||||
install_requires =
|
||||
rich>=10.0.0
|
||||
opentelemetry-api ~= 1.3
|
||||
opentelemetry-sdk ~= 1.3
|
||||
opentelemetry-semantic-conventions == 0.24b0
|
||||
|
||||
[options.packages.find]
|
||||
where = src
|
||||
|
||||
[options.extras_require]
|
||||
test =
|
27
exporter/opentelemetry-exporter-richconsole/setup.py
Normal file
27
exporter/opentelemetry-exporter-richconsole/setup.py
Normal file
@ -0,0 +1,27 @@
|
||||
# Copyright The OpenTelemetry Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
|
||||
import setuptools
|
||||
|
||||
BASE_DIR = os.path.dirname(__file__)
|
||||
VERSION_FILENAME = os.path.join(
|
||||
BASE_DIR, "src", "opentelemetry", "exporter", "richconsole", "version.py"
|
||||
)
|
||||
PACKAGE_INFO = {}
|
||||
with open(VERSION_FILENAME) as f:
|
||||
exec(f.read(), PACKAGE_INFO)
|
||||
|
||||
setuptools.setup(version=PACKAGE_INFO["__version__"])
|
@ -0,0 +1,173 @@
|
||||
# Copyright The OpenTelemetry Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""
|
||||
The **OpenTelemetry Rich Console Exporter** provides a span exporter from a batch span processor
|
||||
to print `OpenTelemetry`_ traces using `Rich`_.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
::
|
||||
|
||||
pip install opentelemetry-exporter-richconsole
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The Rich Console Exporter is a console exporter that prints a tree view onto stdout of the traces
|
||||
with the related spans and properties as children of that tree. For the tree view, the Rich
|
||||
Console Exporter should be used with a BatchSpanProcessor. If used within a SimpleSpanProcessor,
|
||||
all spans will be printed in a list.
|
||||
|
||||
.. code:: python
|
||||
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
||||
from opentelemetry.exporter.richconsole import RichConsoleExporter
|
||||
from opentelemetry.sdk.trace import TracerProvider
|
||||
|
||||
trace.set_tracer_provider(TracerProvider())
|
||||
tracer = trace.get_tracer(__name__)
|
||||
|
||||
tracer.add_span_processor(BatchSpanProcessor(RichConsoleExporter()))
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
.. _Rich: https://rich.readthedocs.io/
|
||||
.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/
|
||||
"""
|
||||
# pylint: disable=import-error
|
||||
|
||||
import datetime
|
||||
import typing
|
||||
from typing import Optional
|
||||
|
||||
from rich.console import Console
|
||||
from rich.syntax import Syntax
|
||||
from rich.text import Text
|
||||
from rich.tree import Tree
|
||||
|
||||
import opentelemetry.trace
|
||||
from opentelemetry.sdk.trace import ReadableSpan
|
||||
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
||||
from opentelemetry.semconv.trace import SpanAttributes
|
||||
|
||||
|
||||
def _ns_to_time(nanoseconds):
|
||||
ts = datetime.datetime.utcfromtimestamp(nanoseconds / 1e9)
|
||||
return ts.strftime("%H:%M:%S.%f")
|
||||
|
||||
|
||||
def _child_to_tree(child: Tree, span: ReadableSpan):
|
||||
child.add(
|
||||
Text.from_markup(f"[bold cyan]Kind :[/bold cyan] {span.kind.name}")
|
||||
)
|
||||
if not span.status.is_unset:
|
||||
if not span.status.is_ok:
|
||||
child.add(
|
||||
Text.from_markup(
|
||||
f"[bold cyan]Status :[/bold cyan] [red]{span.status.status_code}[/red]"
|
||||
)
|
||||
)
|
||||
else:
|
||||
child.add(
|
||||
Text.from_markup(
|
||||
f"[bold cyan]Status :[/bold cyan] {span.status.status_code}"
|
||||
)
|
||||
)
|
||||
if span.status.description:
|
||||
child.add(
|
||||
Text.from_markup(
|
||||
f"[bold cyan]Description :[/bold cyan] {span.status.description}"
|
||||
)
|
||||
)
|
||||
|
||||
if span.events:
|
||||
events = child.add(
|
||||
label=Text.from_markup("[bold cyan]Events :[/bold cyan] ")
|
||||
)
|
||||
for event in span.events:
|
||||
event_node = events.add(Text(event.name))
|
||||
for key, val in event.attributes.items():
|
||||
event_node.add(
|
||||
Text.from_markup(f"[bold cyan]{key} :[/bold cyan] {val}")
|
||||
)
|
||||
if span.attributes:
|
||||
attributes = child.add(
|
||||
label=Text.from_markup("[bold cyan]Attributes :[/bold cyan] ")
|
||||
)
|
||||
for attribute in span.attributes:
|
||||
if attribute == SpanAttributes.DB_STATEMENT:
|
||||
attributes.add(
|
||||
Text.from_markup(f"[bold cyan]{attribute} :[/bold cyan] ")
|
||||
)
|
||||
attributes.add(Syntax(span.attributes[attribute], "sql"))
|
||||
else:
|
||||
attributes.add(
|
||||
Text.from_markup(
|
||||
f"[bold cyan]{attribute} :[/bold cyan] {span.attributes[attribute]}"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class RichConsoleSpanExporter(SpanExporter):
|
||||
"""Implementation of :class:`SpanExporter` that prints spans to the
|
||||
console.
|
||||
|
||||
Should be used within a BatchSpanProcessor
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, service_name: Optional[str] = None,
|
||||
):
|
||||
self.service_name = service_name
|
||||
self.console = Console()
|
||||
|
||||
def export(self, spans: typing.Sequence[ReadableSpan]) -> SpanExportResult:
|
||||
if not spans:
|
||||
return SpanExportResult.SUCCESS
|
||||
tree = Tree(
|
||||
label=f"Trace {opentelemetry.trace.format_trace_id(spans[0].context.trace_id)}"
|
||||
)
|
||||
parents = {}
|
||||
for span in spans:
|
||||
child = tree.add(
|
||||
label=Text.from_markup(
|
||||
f"[blue][{_ns_to_time(span.start_time)}][/blue] [bold]{span.name}[/bold], span {opentelemetry.trace.format_span_id(span.context.span_id)}"
|
||||
)
|
||||
)
|
||||
parents[span.context.span_id] = child
|
||||
_child_to_tree(child, span)
|
||||
|
||||
for span in spans:
|
||||
if span.parent and span.parent.span_id not in parents:
|
||||
child = tree.add(
|
||||
label=Text.from_markup(
|
||||
f"[blue][{_ns_to_time(span.start_time)}][/blue] [bold]{span.name}[/bold], span {opentelemetry.trace.format_span_id(span.context.span_id)}"
|
||||
)
|
||||
)
|
||||
else:
|
||||
child = parents[span.parent.span_id].add(
|
||||
label=Text.from_markup(
|
||||
f"[blue][{_ns_to_time(span.start_time)}][/blue] [bold]{span.name}[/bold], span {opentelemetry.trace.format_span_id(span.context.span_id)}"
|
||||
)
|
||||
)
|
||||
parents[span.context.span_id] = child
|
||||
_child_to_tree(child, span)
|
||||
|
||||
self.console.print(tree)
|
||||
return SpanExportResult.SUCCESS
|
@ -0,0 +1,15 @@
|
||||
# Copyright The OpenTelemetry Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
__version__ = "0.24b0"
|
Reference in New Issue
Block a user