diff --git a/osprofiler/drivers/jaeger.py b/osprofiler/drivers/jaeger.py index 29e7a61..bde3d70 100644 --- a/osprofiler/drivers/jaeger.py +++ b/osprofiler/drivers/jaeger.py @@ -13,144 +13,18 @@ # License for the specific language governing permissions and limitations # under the License. -import collections -import datetime -import time -from urllib import parse as parser - -from oslo_config import cfg -from oslo_serialization import jsonutils - -from osprofiler import _utils as utils from osprofiler.drivers import base from osprofiler import exc +# TODO(tkajinam): Remove this and the deprecated options after G-release class Jaeger(base.Driver): def __init__(self, connection_str, project=None, service=None, host=None, - conf=cfg.CONF, **kwargs): + conf=None, **kwargs): """Jaeger driver for OSProfiler.""" - super().__init__(connection_str, project=project, - service=service, host=host, - conf=conf, **kwargs) - try: - import jaeger_client - self.jaeger_client = jaeger_client - except ImportError: - raise exc.CommandError( - "To use OSProfiler with Uber Jaeger tracer, " - "please install `jaeger-client` library. " - "To install with pip:\n `pip install jaeger-client`." - ) - - parsed_url = parser.urlparse(connection_str) - cfg = { - "local_agent": { - "reporting_host": parsed_url.hostname, - "reporting_port": parsed_url.port, - }, - "tags": conf.profiler_jaeger.process_tags - } - - # Initialize tracer for each profiler - service_name = self._get_service_name(conf, project, service) - config = jaeger_client.Config(cfg, service_name=service_name) - self.tracer = config.initialize_tracer() - - self.spans = collections.deque() - - def _get_service_name(self, conf, project, service): - prefix = conf.profiler_jaeger.service_name_prefix - if prefix: - return "{}-{}-{}".format(prefix, project, service) - return "{}-{}".format(project, service) + raise exc.CommandError('Jaeger driver is no longer supported') @classmethod def get_name(cls): return "jaeger" - - def notify(self, payload): - if payload["name"].endswith("start"): - timestamp = datetime.datetime.strptime(payload["timestamp"], - "%Y-%m-%dT%H:%M:%S.%f") - epoch = datetime.datetime.utcfromtimestamp(0) - start_time = (timestamp - epoch).total_seconds() - - # Create parent span - child_of = self.jaeger_client.SpanContext( - trace_id=utils.shorten_id(payload["base_id"]), - span_id=utils.shorten_id(payload["parent_id"]), - parent_id=None, - flags=self.jaeger_client.span.SAMPLED_FLAG - ) - - # Create Jaeger Tracing span - span = self.tracer.start_span( - operation_name=payload["name"].rstrip("-start"), - child_of=child_of, - tags=self.create_span_tags(payload), - start_time=start_time - ) - - # Replace Jaeger Tracing span_id (random id) to OSProfiler span_id - span.context.span_id = utils.shorten_id(payload["trace_id"]) - self.spans.append(span) - else: - span = self.spans.pop() - - # Store result of db call and function call - for call in ("db", "function"): - if payload.get("info", {}).get(call) is not None: - span.set_tag("result", payload["info"][call]["result"]) - - # Span error tag and log - if payload["info"].get("etype") is not None: - span.set_tag("error", True) - span.log_kv({"error.kind": payload["info"]["etype"]}) - span.log_kv({"message": payload["info"]["message"]}) - - span.finish(finish_time=time.time()) - - def get_report(self, base_id): - """Please use Jaeger Tracing UI for this task.""" - return self._parse_results() - - def list_traces(self, fields=None): - """Please use Jaeger Tracing UI for this task.""" - return [] - - def list_error_traces(self): - """Please use Jaeger Tracing UI for this task.""" - return [] - - def create_span_tags(self, payload): - """Create tags for OpenTracing span. - - :param info: Information from OSProfiler trace. - :returns tags: A dictionary contains standard tags - from OpenTracing sematic conventions, - and some other custom tags related to http, db calls. - """ - tags = {} - info = payload["info"] - - if info.get("db"): - # DB calls - tags["db.statement"] = info["db"]["statement"] - tags["db.params"] = jsonutils.dumps(info["db"]["params"]) - elif info.get("request"): - # WSGI call - tags["http.path"] = info["request"]["path"] - tags["http.query"] = info["request"]["query"] - tags["http.method"] = info["request"]["method"] - tags["http.scheme"] = info["request"]["scheme"] - elif info.get("function"): - # RPC, function calls - if "args" in info["function"]: - tags["args"] = info["function"]["args"] - if "kwargs" in info["function"]: - tags["kwargs"] = info["function"]["kwargs"] - tags["name"] = info["function"]["name"] - - return tags diff --git a/osprofiler/opts.py b/osprofiler/opts.py index 65fd616..1431a75 100644 --- a/osprofiler/opts.py +++ b/osprofiler/opts.py @@ -194,6 +194,8 @@ _jaegerprofiler_opt_group = cfg.OptGroup( _service_name_prefix = cfg.StrOpt( "service_name_prefix", + deprecated_for_removal=True, + deprecated_reason="Jager driver is no longer supported", help=""" Set service name prefix to Jaeger service name. """) @@ -201,6 +203,8 @@ Set service name prefix to Jaeger service name. _process_tags = cfg.DictOpt( "process_tags", default={}, + deprecated_for_removal=True, + deprecated_reason="Jager driver is no longer supported", help=""" Set process tracer tags. """) diff --git a/osprofiler/tests/unit/drivers/test_jaeger.py b/osprofiler/tests/unit/drivers/test_jaeger.py deleted file mode 100644 index e159f6e..0000000 --- a/osprofiler/tests/unit/drivers/test_jaeger.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2018 Fujitsu Ltd. -# All Rights Reserved. -# -# 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. - -from unittest import mock - -from oslo_config import cfg - -from osprofiler.drivers import jaeger -from osprofiler import opts -from osprofiler.tests import test - -from jaeger_client import Config - - -class JaegerTestCase(test.TestCase): - - def setUp(self): - super().setUp() - - opts.set_defaults(cfg.CONF) - cfg.CONF.set_default( - "process_tags", "k1:v1,k2:v2", "profiler_jaeger") - - self.payload_start = { - "name": "api-start", - "base_id": "4e3e0ec6-2938-40b1-8504-09eb1d4b0dee", - "trace_id": "1c089ea8-28fe-4f3d-8c00-f6daa2bc32f1", - "parent_id": "e2715537-3d1c-4f0c-b3af-87355dc5fc5b", - "timestamp": "2018-05-03T04:31:51.781381", - "info": { - "host": "test" - } - } - - self.payload_stop = { - "name": "api-stop", - "base_id": "4e3e0ec6-2938-40b1-8504-09eb1d4b0dee", - "trace_id": "1c089ea8-28fe-4f3d-8c00-f6daa2bc32f1", - "parent_id": "e2715537-3d1c-4f0c-b3af-87355dc5fc5b", - "timestamp": "2018-05-03T04:31:51.781381", - "info": { - "host": "test", - "function": { - "result": 1 - } - } - } - - # Force to False as if already initialized, tracer will be None. - # see: jaeger_client/config.py#L374 - Config._initialized = False - self.driver = jaeger.Jaeger("jaeger://127.0.0.1:6831", - project="nova", service="api", - conf=cfg.CONF) - - @mock.patch("osprofiler._utils.shorten_id") - def test_notify_start(self, mock_shorten_id): - self.driver.notify(self.payload_start) - calls = [ - mock.call(self.payload_start["base_id"]), - mock.call(self.payload_start["parent_id"]), - mock.call(self.payload_start["trace_id"]) - ] - mock_shorten_id.assert_has_calls(calls, any_order=True) - - @mock.patch("jaeger_client.span.Span") - @mock.patch("time.time") - def test_notify_stop(self, mock_time, mock_span): - fake_time = 1525416065.5958152 - mock_time.return_value = fake_time - - span = mock_span() - self.driver.spans.append(mock_span()) - - self.driver.notify(self.payload_stop) - - mock_time.assert_called_once() - mock_time.reset_mock() - - span.finish.assert_called_once_with(finish_time=fake_time) - - def test_service_name_default(self): - self.assertEqual("pr1-svc1", self.driver._get_service_name( - cfg.CONF, "pr1", "svc1")) - - def test_service_name_prefix(self): - cfg.CONF.set_default( - "service_name_prefix", "prx1", "profiler_jaeger") - self.assertEqual("prx1-pr1-svc1", self.driver._get_service_name( - cfg.CONF, "pr1", "svc1")) - - def test_process_tags(self): - tags = self.driver.tracer.tags - # Let's remove variable tags generated by Jaeger client - del tags['hostname'] - del tags['jaeger.version'] - del tags['ip'] - self.assertEqual({'k1': 'v1', 'k2': 'v2'}, tags) diff --git a/releasenotes/notes/retire-jaeger-driver-d8add44c5522ad7a.yaml b/releasenotes/notes/retire-jaeger-driver-d8add44c5522ad7a.yaml new file mode 100644 index 0000000..765f57a --- /dev/null +++ b/releasenotes/notes/retire-jaeger-driver-d8add44c5522ad7a.yaml @@ -0,0 +1,6 @@ +--- +upgrade: + - | + The Jager driver is no longer supported and now using it raises + CommandError. This is because the jaeger-client-python library, which is + its core dependency, was already retired. diff --git a/setup.cfg b/setup.cfg index 6b8181c..6544fbe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,8 +29,6 @@ packages = [extras] elasticsearch = elasticsearch>=2.0.0 # Apache-2.0 -jaeger = - jaeger-client>=3.8.0 # Apache-2.0 messaging = oslo.messaging>=14.1.0 # Apache-2.0 mongo = diff --git a/test-requirements.txt b/test-requirements.txt index e404ca4..b2fe737 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -12,8 +12,6 @@ elasticsearch>=2.0.0 # Apache-2.0 # Redis python client redis>=2.10.0 # MIT -# For Jaeger Tracing -jaeger-client>=3.8.0 # Apache-2.0 -six>=1.10.0 # MIT +# For OTLP opentelemetry-exporter-otlp>=1.16.0 # Apache-2.0 opentelemetry-sdk>=1.16.0 # Apache-2.0