def test_get_report(self): initializer.init_from_conf(CONF, None, self.PROJECT, self.SERVICE, "host") profiler.init("SECRET_KEY", project=self.PROJECT, service=self.SERVICE) foo = DriverTestCase.Foo() foo.bar(1) engine = base.get_driver(CONF.profiler.connection_string, project=self.PROJECT, service=self.SERVICE, host="host", conf=CONF) base_id = profiler.get().get_base_id() res = engine.get_report(base_id) self.assertEqual("total", res["info"]["name"]) self.assertEqual(2, res["stats"]["rpc"]["count"]) self.assertEqual(1, len(res["children"])) cbar = res["children"][0] self._assert_child_dict( cbar, base_id, base_id, "rpc", "osprofiler.tests.functional.test_driver.Foo.bar") self.assertEqual(1, len(cbar["children"])) cbaz = cbar["children"][0] self._assert_child_dict( cbaz, base_id, cbar["trace_id"], "rpc", "osprofiler.tests.functional.test_driver.Foo.baz")
def test_list_traces(self): # initialize profiler notifier (the same way as in services) initializer.init_from_conf( CONF, {}, self.PROJECT, self.SERVICE, "host") profiler.init("SECRET_KEY") # grab base_id base_id = profiler.get().get_base_id() # execute profiled code foo = Foo() foo.bar(1) # instantiate report engine (the same way as in osprofiler CLI) engine = base.get_driver(CONF.profiler.connection_string, project=self.PROJECT, service=self.SERVICE, host="host", conf=CONF) # generate the report traces = engine.list_traces() LOG.debug("Collected traces: %s", traces) # ensure trace with base_id is in the list of traces self.assertIn(base_id, [t["base_id"] for t in traces])
def test_list_traces(self): # initialize profiler notifier (the same way as in services) initializer.init_from_conf(CONF, {}, self.PROJECT, self.SERVICE, "host") profiler.init("SECRET_KEY") # grab base_id base_id = profiler.get().get_base_id() # execute profiled code foo = Foo() foo.bar(1) # instantiate report engine (the same way as in osprofiler CLI) engine = base.get_driver(CONF.profiler.connection_string, project=self.PROJECT, service=self.SERVICE, host="host", conf=CONF) # generate the report traces = engine.list_traces() LOG.debug("Collected traces: %s", traces) # ensure trace with base_id is in the list of traces self.assertIn(base_id, [t["base_id"] for t in traces])
def test_init_and_notify(self): messaging = mock.MagicMock() context = "context" transport = "transport" project = "project" service = "service" host = "host" notify_func = base.get_driver( "messaging://", messaging, context, transport, project, service, host).notify messaging.Notifier.assert_called_once_with( transport, publisher_id=host, driver="messaging", topics=["profiler"], retry=0) info = { "a": 10, "project": project, "service": service, "host": host } notify_func(info) messaging.Notifier().info.assert_called_once_with( context, "profiler.service", info) messaging.reset_mock() notify_func(info, context="my_context") messaging.Notifier().info.assert_called_once_with( "my_context", "profiler.service", info)
def test_build_empty_tree(self): class C(base.Driver): @classmethod def get_name(cls): return "c" self.assertEqual([], base.get_driver("c://")._build_tree({}))
def test_init_and_notify(self): messaging = mock.MagicMock() context = "context" transport = "transport" project = "project" service = "service" host = "host" notify_func = base.get_driver( "messaging://", messaging, context, transport, project, service, host).notify messaging.Notifier.assert_called_once_with( transport, publisher_id=host, driver="messaging", topic="profiler", retry=0) info = { "a": 10, "project": project, "service": service, "host": host } notify_func(info) messaging.Notifier().info.assert_called_once_with( context, "profiler.service", info) messaging.reset_mock() notify_func(info, context="my_context") messaging.Notifier().info.assert_called_once_with( "my_context", "profiler.service", info)
def test_build_empty_tree(self): class C(base.Driver): @classmethod def get_name(cls): return "c" self.assertEqual([], base.get_driver("c://")._build_tree({}))
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()))
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)
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) # 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)
def test_build_complex_tree(self): class D(base.Driver): @classmethod def get_name(cls): return "d" test_input = { "2": {"parent_id": "0", "trace_id": "2", "info": {"started": 1}}, "1": {"parent_id": "0", "trace_id": "1", "info": {"started": 0}}, "21": {"parent_id": "2", "trace_id": "21", "info": {"started": 6}}, "22": {"parent_id": "2", "trace_id": "22", "info": {"started": 7}}, "11": {"parent_id": "1", "trace_id": "11", "info": {"started": 1}}, "113": {"parent_id": "11", "trace_id": "113", "info": {"started": 3}}, "112": {"parent_id": "11", "trace_id": "112", "info": {"started": 2}}, "114": {"parent_id": "11", "trace_id": "114", "info": {"started": 5}} } expected_output = [ { "parent_id": "0", "trace_id": "1", "info": {"started": 0}, "children": [ { "parent_id": "1", "trace_id": "11", "info": {"started": 1}, "children": [ {"parent_id": "11", "trace_id": "112", "info": {"started": 2}, "children": []}, {"parent_id": "11", "trace_id": "113", "info": {"started": 3}, "children": []}, {"parent_id": "11", "trace_id": "114", "info": {"started": 5}, "children": []} ] } ] }, { "parent_id": "0", "trace_id": "2", "info": {"started": 1}, "children": [ {"parent_id": "2", "trace_id": "21", "info": {"started": 6}, "children": []}, {"parent_id": "2", "trace_id": "22", "info": {"started": 7}, "children": []} ] } ] self.assertEqual( expected_output, base.get_driver("d://")._build_tree(test_input))
def test_build_complex_tree(self): class D(base.Driver): @classmethod def get_name(cls): return "d" test_input = { "2": {"parent_id": "0", "trace_id": "2", "info": {"started": 1}}, "1": {"parent_id": "0", "trace_id": "1", "info": {"started": 0}}, "21": {"parent_id": "2", "trace_id": "21", "info": {"started": 6}}, "22": {"parent_id": "2", "trace_id": "22", "info": {"started": 7}}, "11": {"parent_id": "1", "trace_id": "11", "info": {"started": 1}}, "113": {"parent_id": "11", "trace_id": "113", "info": {"started": 3}}, "112": {"parent_id": "11", "trace_id": "112", "info": {"started": 2}}, "114": {"parent_id": "11", "trace_id": "114", "info": {"started": 5}} } expected_output = [ { "parent_id": "0", "trace_id": "1", "info": {"started": 0}, "children": [ { "parent_id": "1", "trace_id": "11", "info": {"started": 1}, "children": [ {"parent_id": "11", "trace_id": "112", "info": {"started": 2}, "children": []}, {"parent_id": "11", "trace_id": "113", "info": {"started": 3}, "children": []}, {"parent_id": "11", "trace_id": "114", "info": {"started": 5}, "children": []} ] } ] }, { "parent_id": "0", "trace_id": "2", "info": {"started": 1}, "children": [ {"parent_id": "2", "trace_id": "21", "info": {"started": 6}, "children": []}, {"parent_id": "2", "trace_id": "22", "info": {"started": 7}, "children": []} ] } ] self.assertEqual( expected_output, base.get_driver("d://")._build_tree(test_input))
def test_factory(self): class A(base.Driver): @classmethod def get_name(cls): return "a" def notify(self, a): return a self.assertEqual(10, base.get_driver("a://").notify(10))
def test_factory(self): class A(base.Driver): @classmethod def get_name(cls): return "a" def notify(self, a): return a self.assertEqual(10, base.get_driver("a://").notify(10))
def test_factory_with_args(self): class B(base.Driver): def __init__(self, c_str, a, b=10): self.a = a self.b = b @classmethod def get_name(cls): return "b" def notify(self, c): return self.a + self.b + c self.assertEqual(22, base.get_driver("b://", 5, b=7).notify(10))
def create(connection_string, *args, **kwargs): """Create notifier based on specified plugin_name :param connection_string: connection string which specifies the storage driver for notifier :param *args: args that will be passed to the driver's __init__ method :param **kwargs: kwargs that will be passed to the driver's __init__ method :returns: Callable notifier method :raises TypeError: In case of invalid name of plugin raises TypeError """ global __driver_cache if connection_string not in __driver_cache: __driver_cache[connection_string] = base.get_driver( connection_string, *args, **kwargs) return __driver_cache[connection_string]
def test_factory_with_args(self): class B(base.Driver): def __init__(self, c_str, a, b=10): self.a = a self.b = b @classmethod def get_name(cls): return "b" def notify(self, c): return self.a + self.b + c self.assertEqual(22, base.get_driver("b://", 5, b=7).notify(10))
def create(connection_string, *args, **kwargs): """Create notifier based on specified plugin_name :param connection_string: connection string which specifies the storage driver for notifier :param *args: args that will be passed to the driver's __init__ method :param **kwargs: kwargs that will be passed to the driver's __init__ method :returns: Callable notifier method :raises TypeError: In case of invalid name of plugin raises TypeError """ global __driver_cache if connection_string not in __driver_cache: __driver_cache[connection_string] = base.get_driver(connection_string, *args, **kwargs).notify return __driver_cache[connection_string]
def _fetch_osprofiler_data(cls, connection_str, trace_id): from osprofiler.drivers import base from osprofiler import opts as osprofiler_opts opts.register_opts(osprofiler_opts.list_opts()) try: engine = base.get_driver(connection_str) except Exception: msg = "Error while fetching OSProfiler results." if logging.is_debug(): LOG.exception(msg) else: LOG.error(msg) return None return engine.get_report(trace_id)
def get_osprofiler_data(cls, data): from osprofiler import cmd from osprofiler.drivers import base from osprofiler import opts as osprofiler_opts opts.register_opts(osprofiler_opts.list_opts()) try: engine = base.get_driver(data["data"]["conn_str"]) except Exception: msg = "Error while fetching OSProfiler results." if logging.is_debug(): LOG.exception(msg) else: LOG.error(msg) return None data["widget"] = "EmbedChart" data["title"] = "{0} : {1}".format(data["title"], data["data"]["trace_id"][0]) path = "%s/template.html" % os.path.dirname(cmd.__file__) with open(path) as f: html_obj = f.read() osp_data = engine.get_report(data["data"]["trace_id"][0]) osp_data = json.dumps(osp_data, indent=4, separators=(",", ": "), default=_datetime_json_serialize) data["data"] = html_obj.replace("$DATA", osp_data) data["data"] = data["data"].replace("$LOCAL", "false") # NOTE(chenxu): self._data will be passed to # ["complete_output"]["data"] as a whole string and # tag </script> will be parsed incorrectly in javascript string # so we turn it to <\/script> and turn it back in javascript. data["data"] = data["data"].replace("/script>", "\/script>") return { "title": data["title"], "widget": data["widget"], "data": data["data"] }
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()))
def test_init_and_notify(self, try_import_mock): context = "context" transport = "transport" project = "project" service = "service" host = "host" # emulate dynamic load of oslo.messaging library oslo_messaging_mock = mock.Mock() try_import_mock.return_value = oslo_messaging_mock # mock oslo.messaging APIs notifier_mock = mock.Mock() oslo_messaging_mock.Notifier.return_value = notifier_mock oslo_messaging_mock.get_notification_transport.return_value = transport notify_func = base.get_driver( "messaging://", project=project, service=service, context=context, host=host).notify oslo_messaging_mock.Notifier.assert_called_once_with( transport, publisher_id=host, driver="messaging", topics=["profiler"], retry=0) info = { "a": 10, "project": project, "service": service, "host": host } notify_func(info) notifier_mock.info.assert_called_once_with( context, "profiler.service", info) notifier_mock.reset_mock() notify_func(info, context="my_context") notifier_mock.info.assert_called_once_with( "my_context", "profiler.service", info)
def test_get_report(self): # initialize profiler notifier (the same way as in services) initializer.init_from_conf(CONF, {}, self.PROJECT, self.SERVICE, "host") profiler.init("SECRET_KEY") # grab base_id base_id = profiler.get().get_base_id() # execute profiled code foo = Foo() foo.bar(1) # instantiate report engine (the same way as in osprofiler CLI) engine = base.get_driver(CONF.profiler.connection_string, project=self.PROJECT, service=self.SERVICE, host="host", conf=CONF) # generate the report report = engine.get_report(base_id) LOG.debug("OSProfiler report: %s", report) # verify the report self.assertEqual("total", report["info"]["name"]) self.assertEqual(2, report["stats"]["rpc"]["count"]) self.assertEqual(1, len(report["children"])) cbar = report["children"][0] self._assert_child_dict( cbar, base_id, base_id, "rpc", "osprofiler.tests.functional.test_driver.Foo.bar") self.assertEqual(1, len(cbar["children"])) cbaz = cbar["children"][0] self._assert_child_dict( cbaz, base_id, cbar["trace_id"], "rpc", "osprofiler.tests.functional.test_driver.Foo.baz")
def test_get_report(self): # initialize profiler notifier (the same way as in services) initializer.init_from_conf( CONF, {}, self.PROJECT, self.SERVICE, "host") profiler.init("SECRET_KEY") # grab base_id base_id = profiler.get().get_base_id() # execute profiled code foo = Foo() foo.bar(1) # instantiate report engine (the same way as in osprofiler CLI) engine = base.get_driver(CONF.profiler.connection_string, project=self.PROJECT, service=self.SERVICE, host="host", conf=CONF) # generate the report report = engine.get_report(base_id) LOG.debug("OSProfiler report: %s", report) # verify the report self.assertEqual("total", report["info"]["name"]) self.assertEqual(2, report["stats"]["rpc"]["count"]) self.assertEqual(1, len(report["children"])) cbar = report["children"][0] self._assert_child_dict( cbar, base_id, base_id, "rpc", "osprofiler.tests.functional.test_driver.Foo.bar") self.assertEqual(1, len(cbar["children"])) cbaz = cbar["children"][0] self._assert_child_dict( cbaz, base_id, cbar["trace_id"], "rpc", "osprofiler.tests.functional.test_driver.Foo.baz")
def test_init_and_notify(self, try_import_mock): context = "context" transport = "transport" project = "project" service = "service" host = "host" # emulate dynamic load of oslo.messaging library oslo_messaging_mock = mock.Mock() try_import_mock.return_value = oslo_messaging_mock # mock oslo.messaging APIs notifier_mock = mock.Mock() oslo_messaging_mock.Notifier.return_value = notifier_mock oslo_messaging_mock.get_notification_transport.return_value = transport notify_func = base.get_driver("messaging://", project=project, service=service, context=context, host=host).notify oslo_messaging_mock.Notifier.assert_called_once_with( transport, publisher_id=host, driver="messaging", topics=["profiler"], retry=0) info = {"a": 10, "project": project, "service": service, "host": host} notify_func(info) notifier_mock.info.assert_called_once_with(context, "profiler.service", info) notifier_mock.reset_mock() notify_func(info, context="my_context") notifier_mock.info.assert_called_once_with("my_context", "profiler.service", info)
def create(connection_string, *args, **kwargs): """Create notifier based on specified plugin_name :param connection_string: connection string which specifies the storage driver for notifier :param args: args that will be passed to the driver's __init__ method :param kwargs: kwargs that will be passed to the driver's __init__ method :returns: Callable notifier method """ global __notifier_cache if connection_string not in __notifier_cache: try: driver = base.get_driver(connection_string, *args, **kwargs) __notifier_cache[connection_string] = driver.notify LOG.info("osprofiler is enabled with connection string: %s", connection_string) except Exception: LOG.exception( "Could not initialize driver for connection string " "%s, osprofiler is disabled", connection_string) __notifier_cache[connection_string] = _noop_notifier return __notifier_cache[connection_string]
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())
def get_osprofiler_data(cls, data): from osprofiler import cmd from osprofiler.drivers import base try: engine = base.get_driver(data["data"]["conn_str"]) except Exception: if logging.is_debug(): LOG.exception("Error while fetching OSProfiler results.") return None data["widget"] = "EmbedChart" data["title"] = "{0} : {1}".format(data["title"], data["data"]["trace_id"][0]) path = "%s/template.html" % os.path.dirname(cmd.__file__) with open(path) as f: html_obj = f.read() osp_data = engine.get_report(data["data"]["trace_id"][0]) osp_data = json.dumps(osp_data, indent=4, separators=(",", ": "), default=_datetime_json_serialize) data["data"] = html_obj.replace("$DATA", osp_data) data["data"] = data["data"].replace("$LOCAL", "false") # NOTE(chenxu): self._data will be passed to # ["complete_output"]["data"] as a whole string and # tag </script> will be parsed incorrectly in javascript string # so we turn it to <\/script> and turn it back in javascript. data["data"] = data["data"].replace("/script>", "\/script>") return {"title": data["title"], "widget": data["widget"], "data": data["data"]}
def test_plugins_are_imported(self): base.get_driver("messaging://", mock.MagicMock(), "context", "transport", "host")
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)