diff --git a/.flake8 b/.flake8 index baa9f02c31b..8431f87079e 100644 --- a/.flake8 +++ b/.flake8 @@ -16,8 +16,10 @@ exclude = venv*/ target __pycache__ - exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/ - exporter/opentelemetry-exporter-jaeger/build/* + exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/ + exporter/opentelemetry-exporter-jaeger-proto/build/* + exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/ + exporter/opentelemetry-exporter-jaeger-thrift/build/* exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/encoder/v2/protobuf/gen/ docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/ docs/examples/opentelemetry-example-app/build/* diff --git a/CHANGELOG.md b/CHANGELOG.md index b87debc4841..30aeb1209e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#1680](https://github.com/open-telemetry/opentelemetry-python/pull/1680)) - Change Zipkin exporter to obtain service.name from span ([#1696](https://github.com/open-telemetry/opentelemetry-python/pull/1696)) +- Split up `opentelemetry-exporter-jaeger` package into `opentelemetry-exporter-jaeger-proto` and + `opentelemetry-exporter-jaeger-thrift` packages to reduce dependencies for each one. + ([#1694](https://github.com/open-telemetry/opentelemetry-python/pull/1694)) ### Removed - Removed unused `get_hexadecimal_trace_id` and `get_hexadecimal_span_id` methods. diff --git a/docs/examples/opentracing/main.py b/docs/examples/opentracing/main.py index df5626b043f..09ff51465c3 100755 --- a/docs/examples/opentracing/main.py +++ b/docs/examples/opentracing/main.py @@ -3,7 +3,7 @@ from rediscache import RedisCache from opentelemetry import trace -from opentelemetry.exporter.jaeger import JaegerExporter +from opentelemetry.exporter.jaeger.thrift import JaegerExporter from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor from opentelemetry.shim import opentracing_shim @@ -13,11 +13,7 @@ tracer_provider = trace.get_tracer_provider() # Configure the tracer to export traces to Jaeger -jaeger_exporter = JaegerExporter( - service_name="OpenTracing Shim Example", - agent_host_name="localhost", - agent_port=6831, -) +jaeger_exporter = JaegerExporter(agent_host_name="localhost", agent_port=6831,) span_processor = SimpleSpanProcessor(jaeger_exporter) tracer_provider.add_span_processor(span_processor) diff --git a/docs/exporter/jaeger/jaeger.rst b/docs/exporter/jaeger/jaeger.rst index efbcfbd7d72..ea2e427cbed 100644 --- a/docs/exporter/jaeger/jaeger.rst +++ b/docs/exporter/jaeger/jaeger.rst @@ -1,26 +1,35 @@ -Opentelemetry Jaeger Exporter -============================= +Opentelemetry Jaeger Exporters +============================== .. automodule:: opentelemetry.exporter.jaeger :members: :undoc-members: :show-inheritance: +.. automodule:: opentelemetry.exporter.jaeger.thrift + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: opentelemetry.exporter.jaeger.proto + :members: + :undoc-members: + :show-inheritance: Submodules ---------- -.. automodule:: opentelemetry.exporter.jaeger.gen.jaeger.ttypes +.. automodule:: opentelemetry.exporter.jaeger.thrift.gen.jaeger.ttypes :members: :undoc-members: :show-inheritance: -.. automodule:: opentelemetry.exporter.jaeger.send.thrift +.. automodule:: opentelemetry.exporter.jaeger.thrift.send :members: :undoc-members: :show-inheritance: -.. automodule:: opentelemetry.exporter.jaeger.gen.collector_pb2_grpc +.. automodule:: opentelemetry.exporter.jaeger.proto.gen.collector_pb2_grpc :members: :undoc-members: :show-inheritance: diff --git a/docs/getting_started/jaeger_example.py b/docs/getting_started/jaeger_example.py index 67337414838..77fea2585d2 100644 --- a/docs/getting_started/jaeger_example.py +++ b/docs/getting_started/jaeger_example.py @@ -14,7 +14,7 @@ # jaeger_example.py from opentelemetry import trace -from opentelemetry.exporter import jaeger +from opentelemetry.exporter.jaeger.thrift import JaegerExporter from opentelemetry.sdk.resources import SERVICE_NAME, Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor @@ -25,9 +25,7 @@ ) ) -jaeger_exporter = jaeger.JaegerExporter( - agent_host_name="localhost", agent_port=6831, -) +jaeger_exporter = JaegerExporter(agent_host_name="localhost", agent_port=6831,) trace.get_tracer_provider().add_span_processor( BatchSpanProcessor(jaeger_exporter) diff --git a/exporter/opentelemetry-exporter-jaeger-proto/LICENSE b/exporter/opentelemetry-exporter-jaeger-proto/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-proto/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/exporter/opentelemetry-exporter-jaeger-proto/MANIFEST.in b/exporter/opentelemetry-exporter-jaeger-proto/MANIFEST.in new file mode 100644 index 00000000000..aed3e33273b --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-proto/MANIFEST.in @@ -0,0 +1,9 @@ +graft src +graft tests +global-exclude *.pyc +global-exclude *.pyo +global-exclude __pycache__/* +include CHANGELOG.md +include MANIFEST.in +include README.rst +include LICENSE diff --git a/exporter/opentelemetry-exporter-jaeger-proto/README.rst b/exporter/opentelemetry-exporter-jaeger-proto/README.rst new file mode 100644 index 00000000000..bd1a0a64f0a --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-proto/README.rst @@ -0,0 +1,36 @@ +OpenTelemetry Jaeger Protobuf Exporter +====================================== + +|pypi| + +.. |pypi| image:: https://badge.fury.io/py/opentelemetry-exporter-jaeger-proto.svg + :target: https://pypi.org/project/opentelemetry-exporter-jaeger-proto/ + +This library allows to export tracing data to `Jaeger `_. + +Installation +------------ + +:: + + pip install opentelemetry-exporter-jaeger-proto + + +.. _Jaeger: https://www.jaegertracing.io/ +.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/ + +Configuration +------------- + +OpenTelemetry Jaeger Exporter can be configured by setting `JaegerExporter parameters +`_ or by setting +`environment variables `_ + +References +---------- + +* `OpenTelemetry Jaeger Exporter `_ +* `Jaeger `_ +* `OpenTelemetry Project `_ diff --git a/exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py b/exporter/opentelemetry-exporter-jaeger-proto/examples/jaeger_exporter_example.py similarity index 69% rename from exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py rename to exporter/opentelemetry-exporter-jaeger-proto/examples/jaeger_exporter_example.py index 35e83f18f3c..9eb7389735c 100644 --- a/exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py +++ b/exporter/opentelemetry-exporter-jaeger-proto/examples/jaeger_exporter_example.py @@ -1,37 +1,22 @@ import time from opentelemetry import trace -from opentelemetry.exporter import jaeger +from opentelemetry.exporter.jaeger import proto from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) -# create a JaegerExporter -jaeger_exporter = jaeger.JaegerExporter( - # configure agent - agent_host_name="localhost", - agent_port=6831, - # optional: configure also collector - # collector_host_name="localhost", - # collector_port=14268, - # collector_endpoint="/api/traces?format=jaeger.thrift", - # username=xxxx, # optional - # password=xxxx, # optional -) - # Create a JaegerExporter to send spans with gRPC # If there is no encryption or authentication set `insecure` to True # If server has authentication with SSL/TLS you can set the # parameter credentials=ChannelCredentials(...) or the environment variable # `EXPORTER_JAEGER_CERTIFICATE` with file containing creds. -# jaeger_exporter = jaeger.JaegerExporter( -# collector_endpoint="localhost:14250", -# insecure=True, -# transport_format="protobuf", -# ) +jaeger_exporter = proto.JaegerExporter( + collector_endpoint="localhost:14250", insecure=True, +) # create a BatchSpanProcessor and add the exporter to it span_processor = BatchSpanProcessor(jaeger_exporter) diff --git a/exporter/opentelemetry-exporter-jaeger/proto/api_v2/collector.proto b/exporter/opentelemetry-exporter-jaeger-proto/proto/api_v2/collector.proto similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/proto/api_v2/collector.proto rename to exporter/opentelemetry-exporter-jaeger-proto/proto/api_v2/collector.proto diff --git a/exporter/opentelemetry-exporter-jaeger/proto/api_v2/model.proto b/exporter/opentelemetry-exporter-jaeger-proto/proto/api_v2/model.proto similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/proto/api_v2/model.proto rename to exporter/opentelemetry-exporter-jaeger-proto/proto/api_v2/model.proto diff --git a/exporter/opentelemetry-exporter-jaeger-proto/setup.cfg b/exporter/opentelemetry-exporter-jaeger-proto/setup.cfg new file mode 100644 index 00000000000..3122904f61a --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-proto/setup.cfg @@ -0,0 +1,56 @@ +# 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-jaeger-proto +description = Jaeger Protobuf 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/tree/main/exporter/opentelemetry-exporter-jaeger-proto +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.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + +[options] +python_requires = >=3.5 +package_dir= + =src +packages=find_namespace: +install_requires = + grpcio >= 1.0.0, < 2.0.0 + googleapis-common-protos ~= 1.52.0 + opentelemetry-api == 1.0.0.dev0 + opentelemetry-sdk == 1.0.0.dev0 + +[options.packages.find] +where = src + +[options.extras_require] +test = + +[options.entry_points] +opentelemetry_exporter = + jaeger_proto = opentelemetry.exporter.jaeger.proto:JaegerExporter \ No newline at end of file diff --git a/exporter/opentelemetry-exporter-jaeger-proto/setup.py b/exporter/opentelemetry-exporter-jaeger-proto/setup.py new file mode 100644 index 00000000000..2cc98f9b0b7 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-proto/setup.py @@ -0,0 +1,32 @@ +# 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", + "jaeger", + "proto", + "version.py", +) +PACKAGE_INFO = {} +with open(VERSION_FILENAME) as f: + exec(f.read(), PACKAGE_INFO) + +setuptools.setup(version=PACKAGE_INFO["__version__"]) diff --git a/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/__init__.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/__init__.py new file mode 100644 index 00000000000..77a29fd09a5 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/__init__.py @@ -0,0 +1,176 @@ +# Copyright 2018, OpenCensus Authors +# 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. + +""" + +OpenTelemetry Jaeger Protobuf Exporter +-------------------------------------- + +The **OpenTelemetry Jaeger Protobuf Exporter** allows to export `OpenTelemetry`_ traces to `Jaeger`_. +This exporter always sends traces to the configured agent using Protobuf via gRPC. + +Usage +----- + +.. code:: python + + from opentelemetry import trace + from opentelemetry.exporter.jaeger.proto import JaegerExporter + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import BatchSpanProcessor + + trace.set_tracer_provider(TracerProvider()) + tracer = trace.get_tracer(__name__) + + # create a JaegerExporter + jaeger_exporter = JaegerExporter( + # optional: configure collector + # collector_endpoint='localhost:14250', + # insecure=True, # optional + # credentials=xxx # optional channel creds + # max_tag_value_length=None # optional + ) + + # Create a BatchSpanProcessor and add the exporter to it + span_processor = BatchSpanProcessor(jaeger_exporter) + + # add to the tracer + trace.get_tracer_provider().add_span_processor(span_processor) + + with tracer.start_as_current_span('foo'): + print('Hello world!') + +You can configure the exporter with the following environment variables: + +- :envvar:`OTEL_EXPORTER_JAEGER_ENDPOINT` +- :envvar:`OTEL_EXPORTER_JAEGER_CERTIFICATE` + +API +--- +.. _Jaeger: https://www.jaegertracing.io/ +.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/ +""" +# pylint: disable=protected-access + +import logging +from os import environ +from typing import Optional + +from grpc import ChannelCredentials, insecure_channel, secure_channel + +from opentelemetry import trace +from opentelemetry.exporter.jaeger.proto import util +from opentelemetry.exporter.jaeger.proto.gen import model_pb2 +from opentelemetry.exporter.jaeger.proto.gen.collector_pb2 import ( + PostSpansRequest, +) +from opentelemetry.exporter.jaeger.proto.gen.collector_pb2_grpc import ( + CollectorServiceStub, +) +from opentelemetry.exporter.jaeger.proto.translate import ( + ProtobufTranslator, + Translate, +) +from opentelemetry.sdk.environment_variables import ( + OTEL_EXPORTER_JAEGER_ENDPOINT, +) +from opentelemetry.sdk.resources import SERVICE_NAME, Resource +from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult + +DEFAULT_GRPC_COLLECTOR_ENDPOINT = "localhost:14250" + +logger = logging.getLogger(__name__) + + +class JaegerExporter(SpanExporter): + """Jaeger span exporter for OpenTelemetry. + + Args: + collector_endpoint: The endpoint of the Jaeger collector that uses + Protobuf via gRPC. + insecure: True if collector has no encryption or authentication + credentials: Credentials for server authentication. + max_tag_value_length: Max length string attribute values can have. Set to None to disable. + """ + + def __init__( + self, + collector_endpoint: Optional[str] = None, + insecure: Optional[bool] = None, + credentials: Optional[ChannelCredentials] = None, + max_tag_value_length: Optional[int] = None, + ): + self._max_tag_value_length = max_tag_value_length + + self.collector_endpoint = _parameter_setter( + param=collector_endpoint, + env_variable=environ.get(OTEL_EXPORTER_JAEGER_ENDPOINT), + default=None, + ) + self._grpc_client = None + self.insecure = insecure + self.credentials = util._get_credentials(credentials) + tracer_provider = trace.get_tracer_provider() + self.service_name = ( + tracer_provider.resource.attributes[SERVICE_NAME] + if getattr(tracer_provider, "resource", None) + else Resource.create().attributes.get(SERVICE_NAME) + ) + + @property + def _collector_grpc_client(self) -> Optional[CollectorServiceStub]: + endpoint = self.collector_endpoint or DEFAULT_GRPC_COLLECTOR_ENDPOINT + + if self._grpc_client is None: + if self.insecure: + self._grpc_client = CollectorServiceStub( + insecure_channel(endpoint) + ) + else: + self._grpc_client = CollectorServiceStub( + secure_channel(endpoint, self.credentials) + ) + return self._grpc_client + + def export(self, spans) -> SpanExportResult: + translator = Translate(spans) + pb_translator = ProtobufTranslator( + self.service_name, self._max_tag_value_length + ) + jaeger_spans = translator._translate(pb_translator) + batch = model_pb2.Batch(spans=jaeger_spans) + request = PostSpansRequest(batch=batch) + self._collector_grpc_client.PostSpans(request) + + return SpanExportResult.SUCCESS + + def shutdown(self): + pass + + +def _parameter_setter(param, env_variable, default): + """Returns value according to the provided data. + + Args: + param: Constructor parameter value + env_variable: Environment variable related to the parameter + default: Constructor parameter default value + """ + if param is None: + res = env_variable or default + else: + res = param + + return res diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/__init__.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/__init__.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/__init__.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/__init__.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/collector_pb2.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/collector_pb2.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/collector_pb2.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/collector_pb2.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/collector_pb2_grpc.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/collector_pb2_grpc.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/collector_pb2_grpc.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/collector_pb2_grpc.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/gogoproto/gogo_pb2.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/gogoproto/gogo_pb2.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/gogoproto/gogo_pb2.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/gogoproto/gogo_pb2.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/google/api/annotations_pb2.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/google/api/annotations_pb2.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/google/api/annotations_pb2.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/google/api/annotations_pb2.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/google/api/http_pb2.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/google/api/http_pb2.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/google/api/http_pb2.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/google/api/http_pb2.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/model_pb2.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/model_pb2.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/model_pb2.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/model_pb2.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/protoc_gen_swagger/options/annotations_pb2.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/protoc_gen_swagger/options/annotations_pb2.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/protoc_gen_swagger/options/annotations_pb2.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/protoc_gen_swagger/options/annotations_pb2.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/protoc_gen_swagger/options/openapiv2_pb2.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/protoc_gen_swagger/options/openapiv2_pb2.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/protoc_gen_swagger/options/openapiv2_pb2.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen/protoc_gen_swagger/options/openapiv2_pb2.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/send/__init__.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/send/__init__.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/send/__init__.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/send/__init__.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/protobuf.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/translate/__init__.py similarity index 82% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/protobuf.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/translate/__init__.py index 011e24f17f2..6a346000b47 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/protobuf.py +++ b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/translate/__init__.py @@ -12,21 +12,93 @@ # See the License for the specific language governing permissions and # limitations under the License. +import abc from typing import Optional, Sequence from google.protobuf.duration_pb2 import Duration from google.protobuf.timestamp_pb2 import Timestamp -from opentelemetry.exporter.jaeger.gen import model_pb2 -from opentelemetry.exporter.jaeger.translate import ( - NAME_KEY, - OTLP_JAEGER_SPAN_KIND, - VERSION_KEY, - Translator, -) +from opentelemetry.exporter.jaeger.proto.gen import model_pb2 + from opentelemetry.sdk.trace import ReadableSpan, StatusCode +from opentelemetry.trace import SpanKind from opentelemetry.util import types + +OTLP_JAEGER_SPAN_KIND = { + SpanKind.CLIENT: "client", + SpanKind.SERVER: "server", + SpanKind.CONSUMER: "consumer", + SpanKind.PRODUCER: "producer", + SpanKind.INTERNAL: "internal", +} + +NAME_KEY = "otel.library.name" +VERSION_KEY = "otel.library.version" + + +def _nsec_to_usec_round(nsec: int) -> int: + """Round nanoseconds to microseconds""" + return (nsec + 500) // 10 ** 3 + + +def _convert_int_to_i64(val): + """Convert integer to signed int64 (i64)""" + if val > 0x7FFFFFFFFFFFFFFF: + val -= 0x10000000000000000 + return val + + +class Translator(abc.ABC): + def __init__(self, max_tag_value_length: Optional[int] = None): + self._max_tag_value_length = max_tag_value_length + + @abc.abstractmethod + def _translate_span(self, span): + """Translates span to jaeger format. + + Args: + span: span to translate + """ + + @abc.abstractmethod + def _extract_tags(self, span): + """Extracts tags from span and returns list of jaeger Tags. + + Args: + span: span to extract tags + """ + + @abc.abstractmethod + def _extract_refs(self, span): + """Extracts references from span and returns list of jaeger SpanRefs. + + Args: + span: span to extract references + """ + + @abc.abstractmethod + def _extract_logs(self, span): + """Extracts logs from span and returns list of jaeger Logs. + + Args: + span: span to extract logs + """ + + +class Translate: + def __init__(self, spans): + self.spans = spans + + def _translate(self, translator: Translator): + translated_spans = [] + for span in self.spans: + # pylint: disable=protected-access + translated_span = translator._translate_span(span) + translated_spans.append(translated_span) + return translated_spans + + # pylint: disable=no-member,too-many-locals,no-self-use diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/util.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/util.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/util.py rename to exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/util.py diff --git a/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/version.py b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/version.py new file mode 100644 index 00000000000..15eb84e8c08 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/version.py @@ -0,0 +1,16 @@ +# Copyright 2019, OpenCensus Authors +# 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__ = "1.0.0.dev0" diff --git a/exporter/opentelemetry-exporter-jaeger/tests/__init__.py b/exporter/opentelemetry-exporter-jaeger-proto/tests/__init__.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/tests/__init__.py rename to exporter/opentelemetry-exporter-jaeger-proto/tests/__init__.py diff --git a/exporter/opentelemetry-exporter-jaeger/tests/certs/cred.cert b/exporter/opentelemetry-exporter-jaeger-proto/tests/certs/cred.cert similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/tests/certs/cred.cert rename to exporter/opentelemetry-exporter-jaeger-proto/tests/certs/cred.cert diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py b/exporter/opentelemetry-exporter-jaeger-proto/tests/test_jaeger_exporter_protobuf.py similarity index 98% rename from exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py rename to exporter/opentelemetry-exporter-jaeger-proto/tests/test_jaeger_exporter_protobuf.py index 2c2bef7b4f8..237ba54b2f1 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py +++ b/exporter/opentelemetry-exporter-jaeger-proto/tests/test_jaeger_exporter_protobuf.py @@ -19,11 +19,11 @@ # pylint:disable=no-name-in-module # pylint:disable=import-error -import opentelemetry.exporter.jaeger.gen.model_pb2 as model_pb2 -import opentelemetry.exporter.jaeger.translate.protobuf as pb_translator +import opentelemetry.exporter.jaeger.proto.gen.model_pb2 as model_pb2 +import opentelemetry.exporter.jaeger.proto.translate as pb_translator from opentelemetry import trace as trace_api -from opentelemetry.exporter.jaeger import JaegerExporter -from opentelemetry.exporter.jaeger.translate import ( +from opentelemetry.exporter.jaeger.proto import JaegerExporter +from opentelemetry.exporter.jaeger.proto.translate import ( NAME_KEY, VERSION_KEY, Translate, @@ -75,7 +75,7 @@ def test_constructor_by_environment_variables(self): env_patch.start() provider = TracerProvider(resource=Resource.create({})) trace_api.set_tracer_provider(provider) - exporter = JaegerExporter(transport_format="protobuf") + exporter = JaegerExporter() self.assertEqual(exporter.service_name, service) self.assertIsNotNone(exporter._collector_grpc_client) self.assertEqual(exporter.collector_endpoint, collector_endpoint) diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/LICENSE b/exporter/opentelemetry-exporter-jaeger-thrift/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-thrift/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/MANIFEST.in b/exporter/opentelemetry-exporter-jaeger-thrift/MANIFEST.in new file mode 100644 index 00000000000..aed3e33273b --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-thrift/MANIFEST.in @@ -0,0 +1,9 @@ +graft src +graft tests +global-exclude *.pyc +global-exclude *.pyo +global-exclude __pycache__/* +include CHANGELOG.md +include MANIFEST.in +include README.rst +include LICENSE diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/README.rst b/exporter/opentelemetry-exporter-jaeger-thrift/README.rst new file mode 100644 index 00000000000..ed6bb1d7925 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-thrift/README.rst @@ -0,0 +1,36 @@ +OpenTelemetry Jaeger Thrift Exporter +==================================== + +|pypi| + +.. |pypi| image:: https://badge.fury.io/py/opentelemetry-exporter-jaeger-thrift.svg + :target: https://pypi.org/project/opentelemetry-exporter-jaeger-thrift/ + +This library allows to export tracing data to `Jaeger `_ using Thrift. + +Installation +------------ + +:: + + pip install opentelemetry-exporter-jaeger-thrift + + +.. _Jaeger: https://www.jaegertracing.io/ +.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/ + +Configuration +------------- + +OpenTelemetry Jaeger Exporter can be configured by setting `JaegerExporter parameters +`_ or by setting +`environment variables `_ + +References +---------- + +* `OpenTelemetry Jaeger Exporter `_ +* `Jaeger `_ +* `OpenTelemetry Project `_ diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/examples/jaeger_exporter_example.py b/exporter/opentelemetry-exporter-jaeger-thrift/examples/jaeger_exporter_example.py new file mode 100644 index 00000000000..1dc138c1dae --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-thrift/examples/jaeger_exporter_example.py @@ -0,0 +1,45 @@ +import time + +from opentelemetry import trace +from opentelemetry.exporter.jaeger import thrift +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor + +trace.set_tracer_provider(TracerProvider()) +tracer = trace.get_tracer(__name__) + +# create a JaegerExporter +jaeger_exporter = thrift.JaegerExporter( + # configure agent + agent_host_name="localhost", + agent_port=6831, + # optional: configure also collector + # collector_endpoint="http://localhost:14268/api/traces?format=jaeger.thrift", + # username=xxxx, # optional + # password=xxxx, # optional +) + +# create a BatchSpanProcessor and add the exporter to it +span_processor = BatchSpanProcessor(jaeger_exporter) + +# add to the tracer factory +trace.get_tracer_provider().add_span_processor(span_processor) + +# create some spans for testing +with tracer.start_as_current_span("foo") as foo: + time.sleep(0.1) + foo.set_attribute("my_atribbute", True) + foo.add_event("event in foo", {"name": "foo1"}) + with tracer.start_as_current_span( + "bar", links=[trace.Link(foo.get_span_context())] + ) as bar: + time.sleep(0.2) + bar.set_attribute("speed", 100.0) + + with tracer.start_as_current_span("baz") as baz: + time.sleep(0.3) + baz.set_attribute("name", "mauricio") + + time.sleep(0.2) + + time.sleep(0.1) diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/setup.cfg b/exporter/opentelemetry-exporter-jaeger-thrift/setup.cfg new file mode 100644 index 00000000000..5ab20acdf26 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-thrift/setup.cfg @@ -0,0 +1,55 @@ +# 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-jaeger-thrift +description = Jaeger Thrift 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/tree/main/exporter/opentelemetry-exporter-jaeger-thrift +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.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + +[options] +python_requires = >=3.5 +package_dir= + =src +packages=find_namespace: +install_requires = + thrift >= 0.10.0 + opentelemetry-api == 1.0.0.dev0 + opentelemetry-sdk == 1.0.0.dev0 + +[options.packages.find] +where = src + +[options.extras_require] +test = + +[options.entry_points] +opentelemetry_exporter = + jaeger_thrift = opentelemetry.exporter.jaeger.thrift:JaegerExporter \ No newline at end of file diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/setup.py b/exporter/opentelemetry-exporter-jaeger-thrift/setup.py new file mode 100644 index 00000000000..e9200b0c7ac --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-thrift/setup.py @@ -0,0 +1,32 @@ +# 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", + "jaeger", + "thrift", + "version.py", +) +PACKAGE_INFO = {} +with open(VERSION_FILENAME) as f: + exec(f.read(), PACKAGE_INFO) + +setuptools.setup(version=PACKAGE_INFO["__version__"]) diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/__init__.py similarity index 64% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/__init__.py index 6634fcc6e8b..674b9d2bf61 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py +++ b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/__init__.py @@ -14,12 +14,16 @@ # limitations under the License. """ -The **OpenTelemetry Jaeger Exporter** allows to export `OpenTelemetry`_ traces to `Jaeger`_. + +OpenTelemetry Jaeger Thrift Exporter +------------------------------------ + +The **OpenTelemetry Jaeger Thrift Exporter** allows to export `OpenTelemetry`_ traces to `Jaeger`_. This exporter always sends traces to the configured agent using the Thrift compact protocol over UDP. When it is not feasible to deploy Jaeger Agent next to the application, for example, when the application code is running as Lambda function, a collector can be configured to send spans -using either Thrift over HTTP or Protobuf via gRPC. If both agent and collector are configured, -the exporter sends traces only to the collector to eliminate the duplicate entries. +using Thrift over HTTP. If both agent and collector are configured, the exporter sends traces +only to the collector to eliminate the duplicate entries. Usage ----- @@ -27,7 +31,7 @@ .. code:: python from opentelemetry import trace - from opentelemetry.exporter import jaeger + from opentelemetry.exporter.jaeger.thrift import JaegerExporter from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor @@ -35,7 +39,7 @@ tracer = trace.get_tracer(__name__) # create a JaegerExporter - jaeger_exporter = jaeger.JaegerExporter( + jaeger_exporter = JaegerExporter( # configure agent agent_host_name='localhost', agent_port=6831, @@ -43,9 +47,6 @@ # collector_endpoint='http://localhost:14268/api/traces?format=jaeger.thrift', # username=xxxx, # optional # password=xxxx, # optional - # insecure=True, # optional - # credentials=xxx # optional channel creds - # transport_format='protobuf' # optional # max_tag_value_length=None # optional ) @@ -63,9 +64,9 @@ - :envvar:`OTEL_EXPORTER_JAEGER_USER` - :envvar:`OTEL_EXPORTER_JAEGER_PASSWORD` - :envvar:`OTEL_EXPORTER_JAEGER_ENDPOINT` -- :envvar:`OTEL_EXPORTER_JAEGER_CERTIFICATE` - :envvar:`OTEL_EXPORTER_JAEGER_AGENT_PORT` - :envvar:`OTEL_EXPORTER_JAEGER_AGENT_HOST` +- :envvar:`OTEL_EXPORTER_JAEGER_AGENT_SPLIT_OVERSIZED_BATCHES` API --- @@ -78,20 +79,15 @@ from os import environ from typing import Optional -from grpc import ChannelCredentials, insecure_channel, secure_channel - from opentelemetry import trace -from opentelemetry.exporter.jaeger import util -from opentelemetry.exporter.jaeger.gen import model_pb2 -from opentelemetry.exporter.jaeger.gen.collector_pb2 import PostSpansRequest -from opentelemetry.exporter.jaeger.gen.collector_pb2_grpc import ( - CollectorServiceStub, +from opentelemetry.exporter.jaeger.thrift.gen.jaeger import ( + Collector as jaeger_thrift, +) +from opentelemetry.exporter.jaeger.thrift.send import AgentClientUDP, Collector +from opentelemetry.exporter.jaeger.thrift.translate import ( + ThriftTranslator, + Translate, ) -from opentelemetry.exporter.jaeger.gen.jaeger import Collector as jaeger_thrift -from opentelemetry.exporter.jaeger.send.thrift import AgentClientUDP, Collector -from opentelemetry.exporter.jaeger.translate import Translate -from opentelemetry.exporter.jaeger.translate.protobuf import ProtobufTranslator -from opentelemetry.exporter.jaeger.translate.thrift import ThriftTranslator from opentelemetry.sdk.environment_variables import ( OTEL_EXPORTER_JAEGER_AGENT_HOST, OTEL_EXPORTER_JAEGER_AGENT_PORT, @@ -105,12 +101,6 @@ DEFAULT_AGENT_HOST_NAME = "localhost" DEFAULT_AGENT_PORT = 6831 -DEFAULT_GRPC_COLLECTOR_ENDPOINT = "localhost:14250" - -UDP_PACKET_MAX_LENGTH = 65000 - -TRANSPORT_FORMAT_THRIFT = "thrift" -TRANSPORT_FORMAT_PROTOBUF = "protobuf" logger = logging.getLogger(__name__) @@ -122,14 +112,11 @@ class JaegerExporter(SpanExporter): agent_host_name: The host name of the Jaeger-Agent. agent_port: The port of the Jaeger-Agent. collector_endpoint: The endpoint of the Jaeger collector that uses - Thrift over HTTP/HTTPS or Protobuf via gRPC. + Thrift over HTTP/HTTPS. username: The user name of the Basic Auth if authentication is required. password: The password of the Basic Auth if authentication is required. - insecure: True if collector has no encryption or authentication - credentials: Credentials for server authentication. - transport_format: Transport format for exporting spans to collector. max_tag_value_length: Max length string attribute values can have. Set to None to disable. udp_split_oversized_batches: Re-emit oversized batches in smaller chunks. """ @@ -141,9 +128,6 @@ def __init__( collector_endpoint: Optional[str] = None, username: Optional[str] = None, password: Optional[str] = None, - insecure: Optional[bool] = None, - credentials: Optional[ChannelCredentials] = None, - transport_format: Optional[str] = None, max_tag_value_length: Optional[int] = None, udp_split_oversized_batches: bool = None, ): @@ -192,14 +176,6 @@ def __init__( default=None, ) self._collector = None - self._grpc_client = None - self.insecure = insecure - self.credentials = util._get_credentials(credentials) - self.transport_format = ( - transport_format.lower() - if transport_format - else TRANSPORT_FORMAT_THRIFT - ) tracer_provider = trace.get_tracer_provider() self.service_name = ( tracer_provider.resource.attributes[SERVICE_NAME] @@ -207,33 +183,12 @@ def __init__( else Resource.create().attributes.get(SERVICE_NAME) ) - @property - def _collector_grpc_client(self) -> Optional[CollectorServiceStub]: - if self.transport_format != TRANSPORT_FORMAT_PROTOBUF: - return None - - endpoint = self.collector_endpoint or DEFAULT_GRPC_COLLECTOR_ENDPOINT - - if self._grpc_client is None: - if self.insecure: - self._grpc_client = CollectorServiceStub( - insecure_channel(endpoint) - ) - else: - self._grpc_client = CollectorServiceStub( - secure_channel(endpoint, self.credentials) - ) - return self._grpc_client - @property def _collector_http_client(self) -> Optional[Collector]: if self._collector is not None: return self._collector - if ( - self.collector_endpoint is None - or self.transport_format != TRANSPORT_FORMAT_THRIFT - ): + if self.collector_endpoint is None: return None auth = None @@ -248,25 +203,16 @@ def _collector_http_client(self) -> Optional[Collector]: def export(self, spans) -> SpanExportResult: translator = Translate(spans) - if self.transport_format == TRANSPORT_FORMAT_PROTOBUF: - pb_translator = ProtobufTranslator( - self.service_name, self._max_tag_value_length - ) - jaeger_spans = translator._translate(pb_translator) - batch = model_pb2.Batch(spans=jaeger_spans) - request = PostSpansRequest(batch=batch) - self._collector_grpc_client.PostSpans(request) + thrift_translator = ThriftTranslator(self._max_tag_value_length) + jaeger_spans = translator._translate(thrift_translator) + batch = jaeger_thrift.Batch( + spans=jaeger_spans, + process=jaeger_thrift.Process(serviceName=self.service_name), + ) + if self._collector_http_client is not None: + self._collector_http_client.submit(batch) else: - thrift_translator = ThriftTranslator(self._max_tag_value_length) - jaeger_spans = translator._translate(thrift_translator) - batch = jaeger_thrift.Batch( - spans=jaeger_spans, - process=jaeger_thrift.Process(serviceName=self.service_name), - ) - if self._collector_http_client is not None: - self._collector_http_client.submit(batch) - else: - self._agent_client.emit(batch) + self._agent_client.emit(batch) return SpanExportResult.SUCCESS diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/__init__.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/__init__.py new file mode 100644 index 00000000000..52b3cfb3e9c --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/__init__.py @@ -0,0 +1,4 @@ + +import sys +from os.path import dirname +sys.path.append(dirname(__file__)) diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/Agent-remote b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/Agent-remote similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/Agent-remote rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/Agent-remote diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/Agent.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/Agent.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/Agent.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/Agent.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/__init__.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/__init__.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/__init__.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/__init__.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/constants.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/constants.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/constants.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/constants.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/ttypes.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/ttypes.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/agent/ttypes.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/agent/ttypes.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/Collector-remote b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/Collector-remote similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/Collector-remote rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/Collector-remote diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/Collector.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/Collector.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/Collector.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/Collector.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/__init__.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/__init__.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/__init__.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/__init__.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/constants.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/constants.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/constants.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/constants.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/ttypes.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/ttypes.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/jaeger/ttypes.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/jaeger/ttypes.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/ZipkinCollector-remote b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/ZipkinCollector-remote similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/ZipkinCollector-remote rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/ZipkinCollector-remote diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/ZipkinCollector.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/ZipkinCollector.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/ZipkinCollector.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/ZipkinCollector.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/__init__.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/__init__.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/__init__.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/__init__.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/constants.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/constants.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/constants.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/constants.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/ttypes.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/ttypes.py similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen/zipkincore/ttypes.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen/zipkincore/ttypes.py diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/send/thrift.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/send.py similarity index 96% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/send/thrift.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/send.py index fe4f4633196..a04b09c4ac2 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/send/thrift.py +++ b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/send.py @@ -20,8 +20,8 @@ from thrift.protocol import TBinaryProtocol, TCompactProtocol from thrift.transport import THttpClient, TTransport -from opentelemetry.exporter.jaeger.gen.agent import Agent as agent -from opentelemetry.exporter.jaeger.gen.jaeger import Collector as jaeger +from opentelemetry.exporter.jaeger.thrift.gen.agent import Agent as agent +from opentelemetry.exporter.jaeger.thrift.gen.jaeger import Collector as jaeger UDP_PACKET_MAX_LENGTH = 65000 diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/thrift.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/translate/__init__.py similarity index 77% rename from exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/thrift.py rename to exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/translate/__init__.py index 45129601ac3..c48c8bde8f3 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/thrift.py +++ b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/translate/__init__.py @@ -11,21 +11,90 @@ # 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. -# pylint: disable=no-self-use + +import abc from typing import Optional, Sequence -from opentelemetry.exporter.jaeger.gen.jaeger import Collector as TCollector -from opentelemetry.exporter.jaeger.translate import ( - NAME_KEY, - OTLP_JAEGER_SPAN_KIND, - VERSION_KEY, - Translator, - _convert_int_to_i64, - _nsec_to_usec_round, +from opentelemetry.exporter.jaeger.thrift.gen.jaeger import ( + Collector as TCollector, ) from opentelemetry.sdk.trace import ReadableSpan, StatusCode +from opentelemetry.trace import SpanKind from opentelemetry.util import types +OTLP_JAEGER_SPAN_KIND = { + SpanKind.CLIENT: "client", + SpanKind.SERVER: "server", + SpanKind.CONSUMER: "consumer", + SpanKind.PRODUCER: "producer", + SpanKind.INTERNAL: "internal", +} + +NAME_KEY = "otel.library.name" +VERSION_KEY = "otel.library.version" + + +def _nsec_to_usec_round(nsec: int) -> int: + """Round nanoseconds to microseconds""" + return (nsec + 500) // 10 ** 3 + + +def _convert_int_to_i64(val): + """Convert integer to signed int64 (i64)""" + if val > 0x7FFFFFFFFFFFFFFF: + val -= 0x10000000000000000 + return val + + +class Translator(abc.ABC): + def __init__(self, max_tag_value_length: Optional[int] = None): + self._max_tag_value_length = max_tag_value_length + + @abc.abstractmethod + def _translate_span(self, span): + """Translates span to jaeger format. + + Args: + span: span to translate + """ + + @abc.abstractmethod + def _extract_tags(self, span): + """Extracts tags from span and returns list of jaeger Tags. + + Args: + span: span to extract tags + """ + + @abc.abstractmethod + def _extract_refs(self, span): + """Extracts references from span and returns list of jaeger SpanRefs. + + Args: + span: span to extract references + """ + + @abc.abstractmethod + def _extract_logs(self, span): + """Extracts logs from span and returns list of jaeger Logs. + + Args: + span: span to extract logs + """ + + +class Translate: + def __init__(self, spans): + self.spans = spans + + def _translate(self, translator: Translator): + translated_spans = [] + for span in self.spans: + # pylint: disable=protected-access + translated_span = translator._translate_span(span) + translated_spans.append(translated_span) + return translated_spans + def _get_string_tag(key, value: str) -> TCollector.Tag: """Returns jaeger string tag.""" diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/version.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/version.py new file mode 100644 index 00000000000..15eb84e8c08 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/version.py @@ -0,0 +1,16 @@ +# Copyright 2019, OpenCensus Authors +# 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__ = "1.0.0.dev0" diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/tests/__init__.py b/exporter/opentelemetry-exporter-jaeger-thrift/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/tests/certs/cred.cert b/exporter/opentelemetry-exporter-jaeger-thrift/tests/certs/cred.cert new file mode 100644 index 00000000000..e69de29bb2d diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py b/exporter/opentelemetry-exporter-jaeger-thrift/tests/test_jaeger_exporter_thrift.py similarity index 97% rename from exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py rename to exporter/opentelemetry-exporter-jaeger-thrift/tests/test_jaeger_exporter_thrift.py index d7776157391..9fcd69b8179 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py +++ b/exporter/opentelemetry-exporter-jaeger-thrift/tests/test_jaeger_exporter_thrift.py @@ -19,11 +19,13 @@ # pylint:disable=no-name-in-module # pylint:disable=import-error -import opentelemetry.exporter.jaeger as jaeger_exporter +import opentelemetry.exporter.jaeger.thrift as jaeger_exporter from opentelemetry import trace as trace_api -from opentelemetry.exporter.jaeger.gen.jaeger import ttypes as jaeger -from opentelemetry.exporter.jaeger.translate import Translate -from opentelemetry.exporter.jaeger.translate.thrift import ThriftTranslator +from opentelemetry.exporter.jaeger.thrift.gen.jaeger import ttypes as jaeger +from opentelemetry.exporter.jaeger.thrift.translate import ( + ThriftTranslator, + Translate, +) from opentelemetry.sdk import trace from opentelemetry.sdk.environment_variables import ( OTEL_EXPORTER_JAEGER_AGENT_HOST, @@ -53,7 +55,7 @@ def setUp(self): self._test_span.end() # pylint: disable=protected-access - @patch("opentelemetry.exporter.jaeger.trace._TRACER_PROVIDER", None) + @patch("opentelemetry.exporter.jaeger.thrift.trace._TRACER_PROVIDER", None) def test_constructor_default(self): # pylint: disable=protected-access """Test the default values assigned by constructor.""" @@ -78,7 +80,7 @@ def test_constructor_default(self): self.assertTrue(exporter._agent_client is not None) self.assertIsNone(exporter._max_tag_value_length) - @patch("opentelemetry.exporter.jaeger.trace._TRACER_PROVIDER", None) + @patch("opentelemetry.exporter.jaeger.thrift.trace._TRACER_PROVIDER", None) def test_constructor_explicit(self): # pylint: disable=protected-access """Test the constructor passing all the options.""" @@ -123,7 +125,7 @@ def test_constructor_explicit(self): self.assertTrue(exporter._collector_http_client.auth is None) self.assertEqual(exporter._max_tag_value_length, 42) - @patch("opentelemetry.exporter.jaeger.trace._TRACER_PROVIDER", None) + @patch("opentelemetry.exporter.jaeger.thrift.trace._TRACER_PROVIDER", None) def test_constructor_by_environment_variables(self): # pylint: disable=protected-access """Test the constructor using Environment Variables.""" @@ -176,7 +178,7 @@ def test_constructor_by_environment_variables(self): self.assertTrue(exporter._collector_http_client.auth is None) environ_patcher.stop() - @patch("opentelemetry.exporter.jaeger.trace._TRACER_PROVIDER", None) + @patch("opentelemetry.exporter.jaeger.thrift.trace._TRACER_PROVIDER", None) def test_constructor_with_no_traceprovider_resource(self): """Test the constructor when there is no resource attached to trace_provider""" @@ -456,7 +458,7 @@ def test_translate_to_jaeger(self): self.assertEqual(spans, expected_spans) - @patch("opentelemetry.exporter.jaeger.trace._TRACER_PROVIDER", None) + @patch("opentelemetry.exporter.jaeger.thrift.trace._TRACER_PROVIDER", None) def test_export(self): """Test that agent and/or collector are invoked""" diff --git a/exporter/opentelemetry-exporter-jaeger/thrift/agent.thrift b/exporter/opentelemetry-exporter-jaeger-thrift/thrift/agent.thrift similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/thrift/agent.thrift rename to exporter/opentelemetry-exporter-jaeger-thrift/thrift/agent.thrift diff --git a/exporter/opentelemetry-exporter-jaeger/thrift/jaeger.thrift b/exporter/opentelemetry-exporter-jaeger-thrift/thrift/jaeger.thrift similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/thrift/jaeger.thrift rename to exporter/opentelemetry-exporter-jaeger-thrift/thrift/jaeger.thrift diff --git a/exporter/opentelemetry-exporter-jaeger/thrift/zipkincore.thrift b/exporter/opentelemetry-exporter-jaeger-thrift/thrift/zipkincore.thrift similarity index 100% rename from exporter/opentelemetry-exporter-jaeger/thrift/zipkincore.thrift rename to exporter/opentelemetry-exporter-jaeger-thrift/thrift/zipkincore.thrift diff --git a/exporter/opentelemetry-exporter-jaeger/setup.cfg b/exporter/opentelemetry-exporter-jaeger/setup.cfg index d2a446a05f5..e904eb7a2da 100644 --- a/exporter/opentelemetry-exporter-jaeger/setup.cfg +++ b/exporter/opentelemetry-exporter-jaeger/setup.cfg @@ -14,7 +14,7 @@ # [metadata] name = opentelemetry-exporter-jaeger -description = Jaeger Exporter for OpenTelemetry +description = Jaeger Exporters for OpenTelemetry long_description = file: README.rst long_description_content_type = text/x-rst author = OpenTelemetry Authors @@ -32,25 +32,15 @@ classifiers = Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 [options] python_requires = >=3.5 -package_dir= - =src + packages=find_namespace: install_requires = - grpcio >= 1.0.0, < 2.0.0 - googleapis-common-protos ~= 1.52.0 - thrift >= 0.10.0 - opentelemetry-api == 1.0.0.dev0 - opentelemetry-sdk == 1.0.0.dev0 - -[options.packages.find] -where = src + opentelemetry-exporter-jaeger-proto == 1.0.0.dev0 + opentelemetry-exporter-jaeger-thrift == 1.0.0.dev0 [options.extras_require] test = - -[options.entry_points] -opentelemetry_exporter = - jaeger = opentelemetry.exporter.jaeger:JaegerExporter \ No newline at end of file diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/__init__.py b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/__init__.py deleted file mode 100644 index c60820085ac..00000000000 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/__init__.py +++ /dev/null @@ -1,91 +0,0 @@ -# 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 abc -from typing import Optional - -from opentelemetry.trace import SpanKind - -OTLP_JAEGER_SPAN_KIND = { - SpanKind.CLIENT: "client", - SpanKind.SERVER: "server", - SpanKind.CONSUMER: "consumer", - SpanKind.PRODUCER: "producer", - SpanKind.INTERNAL: "internal", -} - -NAME_KEY = "otel.library.name" -VERSION_KEY = "otel.library.version" - - -def _nsec_to_usec_round(nsec: int) -> int: - """Round nanoseconds to microseconds""" - return (nsec + 500) // 10 ** 3 - - -def _convert_int_to_i64(val): - """Convert integer to signed int64 (i64)""" - if val > 0x7FFFFFFFFFFFFFFF: - val -= 0x10000000000000000 - return val - - -class Translator(abc.ABC): - def __init__(self, max_tag_value_length: Optional[int] = None): - self._max_tag_value_length = max_tag_value_length - - @abc.abstractmethod - def _translate_span(self, span): - """Translates span to jaeger format. - - Args: - span: span to translate - """ - - @abc.abstractmethod - def _extract_tags(self, span): - """Extracts tags from span and returns list of jaeger Tags. - - Args: - span: span to extract tags - """ - - @abc.abstractmethod - def _extract_refs(self, span): - """Extracts references from span and returns list of jaeger SpanRefs. - - Args: - span: span to extract references - """ - - @abc.abstractmethod - def _extract_logs(self, span): - """Extracts logs from span and returns list of jaeger Logs. - - Args: - span: span to extract logs - """ - - -class Translate: - def __init__(self, spans): - self.spans = spans - - def _translate(self, translator: Translator): - translated_spans = [] - for span in self.spans: - # pylint: disable=protected-access - translated_span = translator._translate_span(span) - translated_spans.append(translated_span) - return translated_spans diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger.py new file mode 100644 index 00000000000..9f199348ba7 --- /dev/null +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger.py @@ -0,0 +1,30 @@ +# 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 unittest + +# pylint:disable=no-name-in-module +# pylint:disable=import-error +from opentelemetry.exporter.jaeger import proto, thrift + + +# pylint:disable=no-member +class TestJaegerExporter(unittest.TestCase): + def test_constructors(self): + """ Test ensures both exporters can co-exist""" + try: + proto.JaegerExporter() + thrift.JaegerExporter() + except Exception as exc: # pylint: disable=broad-except + self.assertIsNone(exc) diff --git a/pyproject.toml b/pyproject.toml index 5207dd223a1..d45615a1e80 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,8 @@ line-length = 79 exclude = ''' ( /( # generated files - exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/gen| + exporter/opentelemetry-exporter-jaeger-proto/src/opentelemetry/exporter/jaeger/proto/gen| + exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen| exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/encoder/v2/protobuf/gen| opentelemetry-proto/src/opentelemetry/proto/collector| opentelemetry-proto/src/opentelemetry/proto/common| diff --git a/scripts/coverage.sh b/scripts/coverage.sh index 00d98a0ca82..aedfbd29668 100755 --- a/scripts/coverage.sh +++ b/scripts/coverage.sh @@ -34,7 +34,8 @@ cov opentelemetry-sdk cov exporter/opentelemetry-exporter-datadog cov instrumentation/opentelemetry-instrumentation-flask cov instrumentation/opentelemetry-instrumentation-requests -cov exporter/opentelemetry-exporter-jaeger +cov exporter/opentelemetry-exporter-jaeger-proto +cov exporter/opentelemetry-exporter-jaeger-thrift cov instrumentation/opentelemetry-instrumentation-opentracing-shim cov util/opentelemetry-util-http cov exporter/opentelemetry-exporter-zipkin diff --git a/tox.ini b/tox.ini index c1f7e7aca25..556430bfaeb 100644 --- a/tox.ini +++ b/tox.ini @@ -29,7 +29,13 @@ envlist = pypy3-test-core-distro ; opentelemetry-exporter-jaeger - py3{5,6,7,8,9}-test-exporter-jaeger + py3{5,6,7,8,9}-test-exporter-jaeger-combined + + ; opentelemetry-exporter-jaeger-proto + py3{5,6,7,8,9}-test-exporter-jaeger-proto + + ; opentelemetry-exporter-jaeger-thrift + py3{5,6,7,8,9}-test-exporter-jaeger-thrift ; opentelemetry-exporter-opencensus py3{5,6,7,8,9}-test-exporter-opencensus @@ -81,7 +87,9 @@ changedir = test-core-opentracing-shim: shim/opentelemetry-opentracing-shim/tests test-core-distro: opentelemetry-distro/tests - test-exporter-jaeger: exporter/opentelemetry-exporter-jaeger/tests + test-exporter-jaeger-combined: exporter/opentelemetry-exporter-jaeger/tests + test-exporter-jaeger-proto: exporter/opentelemetry-exporter-jaeger-proto/tests + test-exporter-jaeger-thrift: exporter/opentelemetry-exporter-jaeger-thrift/tests test-exporter-opencensus: exporter/opentelemetry-exporter-opencensus/tests test-exporter-otlp: exporter/opentelemetry-exporter-otlp/tests test-exporter-zipkin: exporter/opentelemetry-exporter-zipkin/tests @@ -107,7 +115,9 @@ commands_pre = otlp: pip install {toxinidir}/opentelemetry-proto otlp: pip install {toxinidir}/exporter/opentelemetry-exporter-otlp - exporter-jaeger: pip install {toxinidir}/exporter/opentelemetry-exporter-jaeger + exporter-jaeger-combined: pip install {toxinidir}/exporter/opentelemetry-exporter-jaeger-proto {toxinidir}/exporter/opentelemetry-exporter-jaeger-thrift {toxinidir}/exporter/opentelemetry-exporter-jaeger + exporter-jaeger-proto: pip install {toxinidir}/exporter/opentelemetry-exporter-jaeger-proto + exporter-jaeger-thrift: pip install {toxinidir}/exporter/opentelemetry-exporter-jaeger-thrift opentracing-shim: pip install {toxinidir}/opentelemetry-sdk opentracing-shim: pip install {toxinidir}/shim/opentelemetry-opentracing-shim @@ -159,6 +169,8 @@ commands_pre = python -m pip install -e {toxinidir}/opentelemetry-proto[test] python -m pip install -e {toxinidir}/tests/util[test] python -m pip install -e {toxinidir}/shim/opentelemetry-opentracing-shim[test] + python -m pip install -e {toxinidir}/exporter/opentelemetry-exporter-jaeger-proto[test] + python -m pip install -e {toxinidir}/exporter/opentelemetry-exporter-jaeger-thrift[test] python -m pip install -e {toxinidir}/exporter/opentelemetry-exporter-jaeger[test] python -m pip install -e {toxinidir}/exporter/opentelemetry-exporter-opencensus[test] python -m pip install -e {toxinidir}/exporter/opentelemetry-exporter-otlp[test]