Пример #1
0
    def __init__(self, argv):
        args = self._get_base_parser().parse_args(argv)
        opts.set_defaults(cfg.CONF)

        if not (args.os_auth_token and args.ceilometer_url):
            if not args.os_username:
                raise exc.CommandError(
                    "You must provide a username via either --os-username or "
                    "via env[OS_USERNAME]")

            if not args.os_password:
                raise exc.CommandError(
                    "You must provide a password via either --os-password or "
                    "via env[OS_PASSWORD]")

            if self._no_project_and_domain_set(args):
                # steer users towards Keystone V3 API
                raise exc.CommandError(
                    "You must provide a project_id via either --os-project-id "
                    "or via env[OS_PROJECT_ID] and a domain_name via either "
                    "--os-user-domain-name or via env[OS_USER_DOMAIN_NAME] or "
                    "a domain_id via either --os-user-domain-id or via "
                    "env[OS_USER_DOMAIN_ID]")

            if not args.os_auth_url:
                raise exc.CommandError(
                    "You must provide an auth url via either --os-auth-url or "
                    "via env[OS_AUTH_URL]")

        args.func(args)
Пример #2
0
    def list(self, args):
        """List all traces"""
        if not args.conn_str:
            raise exc.CommandError(
                "You must provide connection string via"
                " either --connection-string or "
                "via env[OSPROFILER_CONNECTION_STRING]")
        try:
            engine = base.get_driver(args.conn_str, **args.__dict__)
        except Exception as e:
            raise exc.CommandError(e.message)

        fields = ("base_id", "timestamp")
        pretty_table = prettytable.PrettyTable(fields)
        pretty_table.align = "l"
        timeformat = '%Y-%m-%dT%H:%M:%S.%f'
        if args.since:
            since = datetime.datetime.strptime(
                args.since, timeformat)
        else:
            since = datetime.datetime.fromtimestamp(0)
        if not args.error_trace:
            traces = engine.list_traces(fields)
        else:
            traces = engine.list_error_traces()
        for trace in traces:
            if since > datetime.datetime.strptime(
                    trace['timestamp'], timeformat):
                continue
            row = [trace[field] for field in fields]
            pretty_table.add_row(row)
        if six.PY3:
            print(encodeutils.safe_encode(pretty_table.get_string()).decode())
        else:
            print(encodeutils.safe_encode(pretty_table.get_string()))
Пример #3
0
    def show(self, args):
        """Display trace results in HTML, JSON or DOT format."""

        trace = None

        if not uuidutils.is_uuid_like(args.trace):
            trace = json.load(open(args.trace))
        else:
            try:
                engine = base.get_driver(args.conn_str, **args.__dict__)
            except Exception as e:
                raise exc.CommandError(e.message)

            trace = engine.get_report(args.trace)

        if not trace or not trace.get("children"):
            msg = ("Trace with UUID %s not found. Please check the HMAC key "
                   "used in the command." % args.trace)
            raise exc.CommandError(msg)

        # NOTE(ayelistratov): Ceilometer translates datetime objects to
        # strings, other drivers store this data in ISO Date format.
        # Since datetime.datetime is not JSON serializable by default,
        # this method will handle that.
        def datetime_json_serialize(obj):
            if hasattr(obj, "isoformat"):
                return obj.isoformat()
            else:
                return obj

        if args.use_json:
            output = json.dumps(trace, default=datetime_json_serialize,
                                separators=(",", ": "),
                                indent=2)
        elif args.use_html:
            with open(os.path.join(os.path.dirname(__file__),
                                   "template.html")) as html_template:
                output = html_template.read().replace(
                    "$DATA", json.dumps(trace, indent=4,
                                        separators=(",", ": "),
                                        default=datetime_json_serialize))
                if args.local_libs:
                    output = output.replace("$LOCAL", "true")
                else:
                    output = output.replace("$LOCAL", "false")
        elif args.use_dot:
            dot_graph = self._create_dot_graph(trace)
            output = dot_graph.source
            if args.render_dot_filename:
                dot_graph.render(args.render_dot_filename, cleanup=True)
        else:
            raise exc.CommandError("You should choose one of the following "
                                   "output formats: json, html or dot.")

        if args.file_name:
            with open(args.file_name, "w+") as output_file:
                output_file.write(output)
        else:
            print(output)
Пример #4
0
    def __init__(self,
                 connection_str,
                 db=0,
                 project=None,
                 service=None,
                 host=None,
                 conf=cfg.CONF,
                 **kwargs):
        """Redis driver for OSProfiler."""

        super(Redis, self).__init__(connection_str,
                                    project=project,
                                    service=service,
                                    host=host,
                                    conf=conf,
                                    **kwargs)
        try:
            from redis import StrictRedis
        except ImportError:
            raise exc.CommandError("To use this command, you should install "
                                   "'redis' manually. Use command:\n "
                                   "'pip install redis'.")

        # only connection over network is supported with schema
        # redis://[:password]@host[:port][/db]
        self.db = StrictRedis.from_url(self.connection_str)
        self.namespace = "osprofiler:"
        self.namespace_error = "osprofiler_error:"
Пример #5
0
    def __init__(self,
                 connection_str,
                 db=0,
                 project=None,
                 service=None,
                 host=None,
                 conf=cfg.CONF,
                 **kwargs):
        """Redis driver for OSProfiler."""

        super(RedisSentinel, self).__init__(connection_str,
                                            project=project,
                                            service=service,
                                            host=host,
                                            conf=conf,
                                            **kwargs)
        try:
            from redis.sentinel import Sentinel
        except ImportError:
            raise exc.CommandError("To use this command, you should install "
                                   "'redis' manually. Use command:\n "
                                   "'pip install redis'.")

        self.conf = conf
        socket_timeout = self.conf.profiler.socket_timeout
        parsed_url = parser.urlparse(self.connection_str)
        sentinel = Sentinel([(parsed_url.hostname, int(parsed_url.port))],
                            password=parsed_url.password,
                            socket_timeout=socket_timeout)
        self.db = sentinel.master_for(self.conf.profiler.sentinel_service_name,
                                      socket_timeout=socket_timeout)
Пример #6
0
    def __init__(self,
                 connection_str,
                 db=0,
                 project=None,
                 service=None,
                 host=None,
                 **kwargs):
        """Redis driver for OSProfiler."""

        super(Redis, self).__init__(connection_str,
                                    project=project,
                                    service=service,
                                    host=host)
        try:
            from redis import StrictRedis
        except ImportError:
            raise exc.CommandError("To use this command, you should install "
                                   "'redis' manually. Use command:\n "
                                   "'pip install redis'.")

        parsed_url = parser.urlparse(self.connection_str)
        self.db = StrictRedis(host=parsed_url.hostname,
                              port=parsed_url.port,
                              db=db)
        self.namespace = "osprofiler:"
    def __init__(self, connection_str, index_name="osprofiler-notifications",
                 project=None, service=None, host=None, conf=cfg.CONF,
                 **kwargs):
        """Elasticsearch driver for OSProfiler."""

        super(ElasticsearchDriver, self).__init__(connection_str,
                                                  project=project,
                                                  service=service,
                                                  host=host,
                                                  conf=conf,
                                                  **kwargs)
        try:
            from elasticsearch import Elasticsearch
        except ImportError:
            raise exc.CommandError(
                "To use this command, you should install "
                "'elasticsearch' manually. Use command:\n "
                "'pip install elasticsearch'.")

        client_url = parser.urlunparse(parser.urlparse(self.connection_str)
                                       ._replace(scheme="http"))
        self.conf = conf
        self.client = Elasticsearch(client_url)
        self.index_name = index_name
        self.index_name_error = "osprofiler-notifications-error"
Пример #8
0
    def __init__(self,
                 connection_str,
                 db=0,
                 project=None,
                 service=None,
                 host=None,
                 conf=cfg.CONF,
                 **kwargs):
        """Redis driver for OSProfiler."""

        super(Redis, self).__init__(connection_str,
                                    project=project,
                                    service=service,
                                    host=host,
                                    conf=conf,
                                    **kwargs)
        try:
            from redis import StrictRedis
        except ImportError:
            raise exc.CommandError(
                "To use OSProfiler with Redis driver, "
                "please install `redis` library. "
                "To install with pip:\n `pip install redis`.")

        # only connection over network is supported with schema
        # redis://[:password]@host[:port][/db]
        self.db = StrictRedis.from_url(self.connection_str)
        self.namespace_opt = "osprofiler_opt:"
        self.namespace = "osprofiler:"  # legacy
        self.namespace_error = "osprofiler_error:"
Пример #9
0
    def __init__(self, connection_str, project=None, service=None, host=None,
                 conf=cfg.CONF, **kwargs):
        """Jaeger driver for OSProfiler."""

        super(Jaeger, self).__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, "
                "you have to install `jaeger-client` manually. "
                "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,
            }
        }

        # Initialize tracer for each profiler
        service_name = "{}-{}".format(project, service)
        config = jaeger_client.Config(cfg, service_name=service_name)
        self.tracer = config.initialize_tracer()

        self.spans = collections.deque()
Пример #10
0
    def __init__(self,
                 connection_str,
                 index_name="osprofiler-notifications",
                 project=None,
                 service=None,
                 host=None,
                 conf=cfg.CONF,
                 **kwargs):
        """Elasticsearch driver for OSProfiler."""

        super(ElasticsearchDriver, self).__init__(connection_str,
                                                  project=project,
                                                  service=service,
                                                  host=host,
                                                  conf=conf,
                                                  **kwargs)
        try:
            from elasticsearch import Elasticsearch
        except ImportError:
            raise exc.CommandError(
                "To use OSProfiler with ElasticSearch driver, "
                "please install `elasticsearch` library. "
                "To install with pip:\n `pip install elasticsearch`.")

        client_url = parser.urlunparse(
            parser.urlparse(self.connection_str)._replace(scheme="http"))
        self.conf = conf
        self.client = Elasticsearch(client_url)
        self.index_name = index_name
        self.index_name_error = "osprofiler-notifications-error"
Пример #11
0
    def db_conn(self):
        try:
            from pymongo import MongoClient
        except ImportError:
            raise exc.CommandError("To use this command, you should install "
                                   "'pymongo' manually. Use command:\n "
                                   "'pip install pymongo'.")

        client = MongoClient(self.connection_str, connect=False)
        self.db = client['osprofiler']
Пример #12
0
    def __init__(self, connection_str, **kwargs):
        """Driver receiving profiled information from ceilometer."""
        super(Ceilometer, self).__init__(connection_str)
        try:
            import ceilometerclient.client
        except ImportError:
            raise exc.CommandError(
                "To use this command, you should install "
                "'ceilometerclient' manually. Use command:\n "
                "'pip install python-ceilometerclient'.")

        try:
            self.client = ceilometerclient.client.get_client(
                kwargs["ceilometer_api_version"], **kwargs)
        except Exception as e:
            if hasattr(e, "http_status") and e.http_status == 401:
                msg = "Invalid OpenStack Identity credentials."
            else:
                msg = "Error occurred while connecting to Ceilometer: %s." % e
            raise exc.CommandError(msg)
Пример #13
0
    def list(self, args):
        """List all traces"""
        if not args.conn_str:
            raise exc.CommandError(
                "You must provide connection string via"
                " either --connection-string or "
                "via env[OSPROFILER_CONNECTION_STRING]")
        try:
            engine = base.get_driver(args.conn_str, **args.__dict__)
        except Exception as e:
            raise exc.CommandError(e.message)

        fields = ("base_id", "timestamp")
        pretty_table = prettytable.PrettyTable(fields)
        pretty_table.align = "l"
        if not args.error_trace:
            traces = engine.list_traces(fields)
        else:
            traces = engine.list_error_traces()
        for trace in traces:
            row = [trace[field] for field in fields]
            pretty_table.add_row(row)
        print(encodeutils.safe_encode(pretty_table.get_string()).decode())
Пример #14
0
    def __init__(self, connection_str, db_name="osprofiler", project=None,
                 service=None, host=None, **kwargs):
        """MongoDB driver for OSProfiler."""

        super(MongoDB, self).__init__(connection_str, project=project,
                                      service=service, host=host, **kwargs)
        try:
            from pymongo import MongoClient
        except ImportError:
            raise exc.CommandError(
                "To use this command, you should install "
                "'pymongo' manually. Use command:\n "
                "'pip install pymongo'.")

        client = MongoClient(self.connection_str, connect=False)
        self.db = client[db_name]
Пример #15
0
 def list_traces(self, fields=None):
     try:
         from sqlalchemy.sql import select
     except ImportError:
         raise exc.CommandError(
             "To use this command, you should install 'SQLAlchemy'")
     stmt = select([self._data_table])
     seen_ids = set()
     result = []
     traces = self._conn.execute(stmt).fetchall()
     for trace in traces:
         if trace["base_id"] not in seen_ids:
             seen_ids.add(trace["base_id"])
             result.append({
                 key: value
                 for key, value in trace.items() if key in fields
             })
     return result
Пример #16
0
    def list(self, args):
        """List all traces"""
        try:
            engine = base.get_driver(args.conn_str, **args.__dict__)
        except Exception as e:
            raise exc.CommandError(e.message)

        fields = ("base_id", "timestamp")
        pretty_table = prettytable.PrettyTable(fields)
        pretty_table.align = "l"
        if not args.error_trace:
            traces = engine.list_traces(fields)
        else:
            traces = engine.list_error_traces()
        for trace in traces:
            row = [trace[field] for field in fields]
            pretty_table.add_row(row)
        if six.PY3:
            print(encodeutils.safe_encode(pretty_table.get_string()).decode())
        else:
            print(encodeutils.safe_encode(pretty_table.get_string()))
Пример #17
0
 def get_report(self, base_id):
     try:
         from sqlalchemy.sql import select
     except ImportError:
         raise exc.CommandError(
             "To use this command, you should install 'SQLAlchemy'")
     stmt = select([self._data_table
                    ]).where(self._data_table.c.base_id == base_id)
     results = self._conn.execute(stmt).fetchall()
     for n in results:
         timestamp = n["timestamp"]
         trace_id = n["trace_id"]
         parent_id = n["parent_id"]
         name = n["name"]
         project = n["project"]
         service = n["service"]
         host = n["host"]
         data = jsonutils.loads(n["data"])
         self._append_results(trace_id, parent_id, name, project, service,
                              host, timestamp, data)
     return self._parse_results()
Пример #18
0
    def _create_dot_graph(self, trace):
        try:
            import graphviz
        except ImportError:
            raise exc.CommandError(
                "graphviz library is required to use this option.")

        dot = graphviz.Digraph(format="pdf")
        next_id = [0]

        def _create_node(info):
            time_taken = info["finished"] - info["started"]
            service = info["service"] + ":" if "service" in info else ""
            name = info["name"]
            label = "%s%s - %d ms" % (service, name, time_taken)

            if name == "wsgi":
                req = info["meta.raw_payload.wsgi-start"]["info"]["request"]
                label = "%s\\n%s %s.." % (label, req["method"],
                                          req["path"][:30])
            elif name == "rpc" or name == "driver":
                raw = info["meta.raw_payload.%s-start" % name]
                fn_name = raw["info"]["function"]["name"]
                label = "%s\\n%s" % (label, fn_name.split(".")[-1])

            node_id = str(next_id[0])
            next_id[0] += 1
            dot.node(node_id, label)
            return node_id

        def _create_sub_graph(root):
            rid = _create_node(root["info"])
            for child in root["children"]:
                cid = _create_sub_graph(child)
                dot.edge(rid, cid)
            return rid

        _create_sub_graph(trace)
        return dot
Пример #19
0
    def __init__(self,
                 connection_str,
                 db_name="osprofiler",
                 project=None,
                 service=None,
                 host=None,
                 **kwargs):
        """MongoDB driver for OSProfiler."""

        super(MongoDB, self).__init__(connection_str,
                                      project=project,
                                      service=service,
                                      host=host,
                                      **kwargs)
        try:
            from pymongo import MongoClient
        except ImportError:
            raise exc.CommandError(
                "To use OSProfiler with MongoDB driver, "
                "please install `pymongo` library. "
                "To install with pip:\n `pip install pymongo`.")

        client = MongoClient(self.connection_str, connect=False)
        self.db = client[db_name]
Пример #20
0
    def show(self, args):
        """Display trace results in HTML, JSON or DOT format."""

        trace = None

        if not uuidutils.is_uuid_like(args.trace):
            trace = json.load(open(args.trace))
        else:
            try:
                engine = base.get_driver(args.conn_str, **args.__dict__)
            except Exception as e:
                raise exc.CommandError(e.message)

            trace = engine.get_report(args.trace)

        if not trace or not trace.get("children"):
            msg = ("Trace with UUID %s not found. "
                   "There are 3 possible reasons: \n"
                   " 1) You are using not admin credentials\n"
                   " 2) You specified wrong trace id\n"
                   " 3) You specified wrong HMAC Key in original calling\n"
                   " 4) Ceilometer didn't enable profiler notification topic" %
                   args.trace)
            raise exc.CommandError(msg)

        # NOTE(ayelistratov): Ceilometer translates datetime objects to
        # strings, other drivers store this data in ISO Date format.
        # Since datetime.datetime is not JSON serializable by default,
        # this method will handle that.
        def datetime_json_serialize(obj):
            if hasattr(obj, "isoformat"):
                return obj.isoformat()
            else:
                return obj

        if args.use_json:
            output = json.dumps(trace,
                                default=datetime_json_serialize,
                                indent=2)
        elif args.use_html:
            with open(os.path.join(os.path.dirname(__file__),
                                   "template.html")) as html_template:
                output = html_template.read().replace(
                    "$DATA",
                    json.dumps(trace,
                               indent=4,
                               default=datetime_json_serialize))
        elif args.use_dot:
            dot_graph = self._create_dot_graph(trace)
            output = dot_graph.source
            if args.render_dot_filename:
                dot_graph.render(args.render_dot_filename, cleanup=True)
        else:
            raise exc.CommandError("You should choose one of the following "
                                   "output formats: json, html or dot.")

        if args.file_name:
            with open(args.file_name, "w+") as output_file:
                output_file.write(output)
        else:
            print(output)
Пример #21
0
 def test_shell_main(self, mock_shell):
     mock_shell.side_effect = exc.CommandError("some_message")
     shell.main()
     self.assertEqual("some_message\n", sys.stdout.getvalue())