From 807b0792040b91831f78ef629a881cc2f065b78c Mon Sep 17 00:00:00 2001 From: Yujun Zhang Date: Thu, 20 Jul 2017 16:20:13 +0800 Subject: [PATCH] Add osprofiler support for RPC, api controllers and handlers Change-Id: I56cde014120d3321fd744fcd919076511790cfa3 Implements: blueprint osprofiler-support --- Dockerfile | 10 +++++ test-requirements.txt | 1 + vitrage/api/controllers/v1/alarm.py | 3 ++ vitrage/api/controllers/v1/event.py | 3 ++ vitrage/api/controllers/v1/rca.py | 3 ++ vitrage/api/controllers/v1/resource.py | 3 ++ vitrage/api/controllers/v1/template.py | 3 ++ vitrage/api/controllers/v1/topology.py | 3 ++ vitrage/api_handler/apis/alarm.py | 3 ++ vitrage/api_handler/apis/event.py | 3 ++ vitrage/api_handler/apis/rca.py | 3 ++ vitrage/api_handler/apis/resource.py | 3 ++ vitrage/api_handler/apis/template.py | 3 ++ vitrage/api_handler/apis/topology.py | 3 ++ vitrage/graph/algo_driver/algorithm.py | 6 +++ vitrage/rpc.py | 52 ++++++++++++++++++++++++++ 16 files changed, 105 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..08664d654 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +############################################################ +# Dockerfile to build container for vitrage development +############################################################ + +FROM vitrage:base +MAINTAINER zhang.yujunz@zte.com.cn + +EXPOSE 8999 + +WORKDIR /opt diff --git a/test-requirements.txt b/test-requirements.txt index cb35c84ac..7759612a5 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -31,6 +31,7 @@ voluptuous>=0.8.9 # BSD License sympy>=0.7.6 # BSD reno!=2.3.1,>=1.8.0 # Apache-2.0 pysnmp!=4.3.4,!=4.3.5,!=4.3.6,!=4.3.7,>=4.2.3 # BSD +osprofiler>=1.4.0 # Apache-2.0 # Doc requirements openstackdocstheme>=1.11.0 # Apache-2.0 diff --git a/vitrage/api/controllers/v1/alarm.py b/vitrage/api/controllers/v1/alarm.py index 72abdbfee..187c923ed 100644 --- a/vitrage/api/controllers/v1/alarm.py +++ b/vitrage/api/controllers/v1/alarm.py @@ -17,6 +17,7 @@ import pecan from oslo_log import log from oslo_utils.strutils import bool_from_string +from osprofiler import profiler from pecan.core import abort from vitrage.api.controllers.rest import RootRestController @@ -26,6 +27,8 @@ from vitrage.api.policy import enforce LOG = log.getLogger(__name__) +@profiler.trace_cls("alarm controller", + info={}, hide_args=False, trace_private=False) class AlarmsController(RootRestController): @pecan.expose('json') diff --git a/vitrage/api/controllers/v1/event.py b/vitrage/api/controllers/v1/event.py index 1ae75caba..0aaaa8855 100644 --- a/vitrage/api/controllers/v1/event.py +++ b/vitrage/api/controllers/v1/event.py @@ -15,6 +15,7 @@ import pecan from oslo_log import log +from osprofiler import profiler from pecan.core import abort from vitrage.api.controllers.rest import RootRestController @@ -24,6 +25,8 @@ from vitrage.api.policy import enforce LOG = log.getLogger(__name__) +@profiler.trace_cls("event controller", + info={}, hide_args=False, trace_private=False) class EventController(RootRestController): @pecan.expose('json') diff --git a/vitrage/api/controllers/v1/rca.py b/vitrage/api/controllers/v1/rca.py index 25e8e68e6..a3b53e786 100644 --- a/vitrage/api/controllers/v1/rca.py +++ b/vitrage/api/controllers/v1/rca.py @@ -18,6 +18,7 @@ import pecan from oslo_log import log from oslo_utils.strutils import bool_from_string +from osprofiler import profiler from pecan.core import abort from vitrage.api.controllers.rest import RootRestController from vitrage.api.policy import enforce @@ -26,6 +27,8 @@ from vitrage.api.policy import enforce LOG = log.getLogger(__name__) +@profiler.trace_cls("rca controller", + info={}, hide_args=False, trace_private=False) class RCAController(RootRestController): @pecan.expose('json') def index(self, alarm_id, all_tenants=False): diff --git a/vitrage/api/controllers/v1/resource.py b/vitrage/api/controllers/v1/resource.py index 446b3f9e4..0e739108f 100644 --- a/vitrage/api/controllers/v1/resource.py +++ b/vitrage/api/controllers/v1/resource.py @@ -14,6 +14,7 @@ import pecan from oslo_log import log from oslo_utils.strutils import bool_from_string +from osprofiler import profiler from pecan.core import abort from vitrage.api.controllers.rest import RootRestController @@ -23,6 +24,8 @@ from vitrage.api.policy import enforce LOG = log.getLogger(__name__) +@profiler.trace_cls("resource controller", + info={}, hide_args=False, trace_private=False) class ResourcesController(RootRestController): @pecan.expose('json') def get_all(self, **kwargs): diff --git a/vitrage/api/controllers/v1/template.py b/vitrage/api/controllers/v1/template.py index 03a20569f..e75360c79 100644 --- a/vitrage/api/controllers/v1/template.py +++ b/vitrage/api/controllers/v1/template.py @@ -15,6 +15,7 @@ import json import pecan from oslo_log import log +from osprofiler import profiler from pecan.core import abort from vitrage.api.controllers.rest import RootRestController @@ -24,6 +25,8 @@ from vitrage.api.policy import enforce LOG = log.getLogger(__name__) +@profiler.trace_cls("template controller", + info={}, hide_args=False, trace_private=False) class TemplateController(RootRestController): @pecan.expose('json') diff --git a/vitrage/api/controllers/v1/topology.py b/vitrage/api/controllers/v1/topology.py index 2a5408759..5cb45eb4d 100644 --- a/vitrage/api/controllers/v1/topology.py +++ b/vitrage/api/controllers/v1/topology.py @@ -17,6 +17,7 @@ import json from oslo_log import log from oslo_utils.strutils import bool_from_string +from osprofiler import profiler import pecan from pecan.core import abort @@ -31,6 +32,8 @@ from vitrage.datasources.transformer_base import CLUSTER_ID LOG = log.getLogger(__name__) +@profiler.trace_cls("topology controller", + info={}, hide_args=False, trace_private=False) class TopologyController(RootRestController): @pecan.expose('json') diff --git a/vitrage/api_handler/apis/alarm.py b/vitrage/api_handler/apis/alarm.py index 06647f013..9a0544ed4 100644 --- a/vitrage/api_handler/apis/alarm.py +++ b/vitrage/api_handler/apis/alarm.py @@ -14,6 +14,7 @@ import json from oslo_log import log +from osprofiler import profiler from vitrage.api_handler.apis.base import ALARM_QUERY from vitrage.api_handler.apis.base import ALARMS_ALL_QUERY @@ -25,6 +26,8 @@ from vitrage.common.constants import VertexProperties as VProps LOG = log.getLogger(__name__) +@profiler.trace_cls("alarm apis", + info={}, hide_args=False, trace_private=False) class AlarmApis(EntityGraphApisBase): def __init__(self, entity_graph, conf): diff --git a/vitrage/api_handler/apis/event.py b/vitrage/api_handler/apis/event.py index d7e907f70..3d2981cf5 100644 --- a/vitrage/api_handler/apis/event.py +++ b/vitrage/api_handler/apis/event.py @@ -16,6 +16,7 @@ from datetime import datetime from oslo_log import log import oslo_messaging from oslo_utils import uuidutils +from osprofiler import profiler import socket from vitrage.api_handler.apis.base import EntityGraphApisBase @@ -25,6 +26,8 @@ from vitrage.messaging import get_transport LOG = log.getLogger(__name__) +@profiler.trace_cls("event apis", + info={}, hide_args=False, trace_private=False) class EventApis(EntityGraphApisBase): def __init__(self, conf): diff --git a/vitrage/api_handler/apis/rca.py b/vitrage/api_handler/apis/rca.py index 70d8546e6..58f6fa38e 100644 --- a/vitrage/api_handler/apis/rca.py +++ b/vitrage/api_handler/apis/rca.py @@ -13,6 +13,7 @@ # under the License. from oslo_log import log +from osprofiler import profiler from vitrage.api_handler.apis.base import ALARMS_ALL_QUERY from vitrage.api_handler.apis.base import EDGE_QUERY @@ -24,6 +25,8 @@ from vitrage.graph import Direction LOG = log.getLogger(__name__) +@profiler.trace_cls("rca apis", + info={}, hide_args=False, trace_private=False) class RcaApis(EntityGraphApisBase): def __init__(self, entity_graph, conf): diff --git a/vitrage/api_handler/apis/resource.py b/vitrage/api_handler/apis/resource.py index 8184d323e..723a1e31f 100644 --- a/vitrage/api_handler/apis/resource.py +++ b/vitrage/api_handler/apis/resource.py @@ -14,6 +14,7 @@ import copy import json from oslo_log import log +from osprofiler import profiler from vitrage.api_handler.apis.base import EntityGraphApisBase from vitrage.api_handler.apis.base import RESOURCES_ALL_QUERY @@ -24,6 +25,8 @@ from vitrage.common.constants import VertexProperties as VProps LOG = log.getLogger(__name__) +@profiler.trace_cls("resource apis", + info={}, hide_args=False, trace_private=False) class ResourceApis(EntityGraphApisBase): def __init__(self, entity_graph, conf): diff --git a/vitrage/api_handler/apis/template.py b/vitrage/api_handler/apis/template.py index edb9f847a..6359761f2 100644 --- a/vitrage/api_handler/apis/template.py +++ b/vitrage/api_handler/apis/template.py @@ -14,6 +14,7 @@ import json from oslo_log import log +from osprofiler import profiler from vitrage.evaluator.template_fields import TemplateFields from vitrage.evaluator.template_validation.content.template_content_validator \ @@ -26,6 +27,8 @@ from vitrage.evaluator.template_validation.template_syntax_validator import \ LOG = log.getLogger(__name__) +@profiler.trace_cls("template apis", + info={}, hide_args=False, trace_private=False) class TemplateApis(object): FAILED_MSG = 'validation failed' diff --git a/vitrage/api_handler/apis/topology.py b/vitrage/api_handler/apis/topology.py index 086521463..2b624cad1 100644 --- a/vitrage/api_handler/apis/topology.py +++ b/vitrage/api_handler/apis/topology.py @@ -13,6 +13,7 @@ # under the License. from oslo_log import log +from osprofiler import profiler from vitrage.api_handler.apis.base import ALARMS_ALL_QUERY from vitrage.api_handler.apis.base import EDGE_QUERY @@ -29,6 +30,8 @@ from vitrage.entity_graph.processor import processor_utils LOG = log.getLogger(__name__) +@profiler.trace_cls("topology apis", + info={}, hide_args=False, trace_private=False) class TopologyApis(EntityGraphApisBase): def __init__(self, entity_graph, conf): diff --git a/vitrage/graph/algo_driver/algorithm.py b/vitrage/graph/algo_driver/algorithm.py index ba40de1d1..9cf9616b3 100644 --- a/vitrage/graph/algo_driver/algorithm.py +++ b/vitrage/graph/algo_driver/algorithm.py @@ -14,14 +14,20 @@ import abc from collections import namedtuple +from osprofiler import profiler import six Mapping = \ namedtuple('Mapping', ['subgraph_element', 'graph_element', 'is_vertex']) +@six.add_metaclass(profiler.TracedMeta) @six.add_metaclass(abc.ABCMeta) class GraphAlgorithm(object): + __trace_args__ = {'name': 'graph', + 'info': None, + 'hide_args': False, + 'trace_private': False} def __init__(self, graph): """Create a new GraphAlgorithm diff --git a/vitrage/rpc.py b/vitrage/rpc.py index 0b342982d..4b6999afb 100644 --- a/vitrage/rpc.py +++ b/vitrage/rpc.py @@ -15,8 +15,10 @@ from oslo_config import cfg +from oslo_log import log import oslo_messaging as messaging from oslo_messaging.rpc import dispatcher +from osprofiler import profiler OPTS = [ cfg.StrOpt('rpc_topic', @@ -24,6 +26,46 @@ OPTS = [ help='The topic vitrage listens on'), ] +LOG = log.getLogger(__name__) + + +class ProfilerContextSerializer(messaging.Serializer): + def __init__(self, base): + self._base = base + + def serialize_entity(self, context, entity): + if not self._base: + return entity + return self._base.serialize_entity(context, entity) + + def deserialize_entity(self, context, entity): + if not self._base: + return entity + return self._base.deserialize_entity(context, entity) + + def serialize_context(self, context): + ctx = self._base.serialize_context(context) if self._base else {} + + pfr = profiler.get() + + if pfr: + ctx['trace_info'] = { + "hmac_key": pfr.hmac_key, + "base_id": pfr.get_base_id(), + "parent_id": pfr.get_id() + } + + return ctx + + def deserialize_context(self, context): + trace_info = context.pop('trace_info', None) + + if trace_info: + profiler.init(**trace_info) + + return self._base.deserialize_context(context)\ + if self._base else context + def set_defaults(control_exchange): messaging.set_transport_defaults(control_exchange) @@ -31,6 +73,11 @@ def set_defaults(control_exchange): def get_client(transport, target, version_cap=None, serializer=None): assert transport is not None + + if profiler: + LOG.info('profiler enabled for RPC client') + serializer = ProfilerContextSerializer(base=serializer) + return messaging.RPCClient(transport, target, version_cap=version_cap, @@ -39,6 +86,11 @@ def get_client(transport, target, version_cap=None, serializer=None): def get_server(target, endpoints, transport, serializer=None): assert transport is not None + + if profiler: + LOG.info('profiler enabled for RPC server') + serializer = ProfilerContextSerializer(base=serializer) + access_policy = dispatcher.DefaultRPCAccessPolicy return messaging.get_rpc_server(transport, target,