)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":29911,"name":"Dantali0n","email":"info@dantalion.nl","username":"Dantali0n"},"change_message_id":"28113e290063ce7f6ffe9c93059e7d285a287756","unresolved":false,"context_lines":[{"line_number":24,"context_line":"1 - https://pyyaml.org/wiki/PyYAMLDocumentation"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Change-Id: I1df16245f4c7dfd34066f3ab0553cd67154faa58"},{"line_number":27,"context_line":"Implements: blueprint file-based-metric-map"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":6,"id":"bfb3d3c7_1a197078","line":27,"updated":"2019-05-18 17:38:32.000000000","message":"nit: Your blueprint url is file-base-metric-map so the links do not work because the d in based is missing. You can change the url of your blueprint on https://blueprints.launchpad.net/watcher/+spec/file-base-metric-map","commit_id":"137a05230f6330d9c7e398de43cbbee76a10ebea"},{"author":{"_account_id":21692,"name":"licanwei","email":"li.canwei2@zte.com.cn","username":"licanwei"},"change_message_id":"a7fc3aa3283c22bc330a7b15a06ebb49df7c915c","unresolved":false,"context_lines":[{"line_number":24,"context_line":"1 - https://pyyaml.org/wiki/PyYAMLDocumentation"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Change-Id: I1df16245f4c7dfd34066f3ab0553cd67154faa58"},{"line_number":27,"context_line":"Implements: blueprint file-based-metric-map"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":6,"id":"bfb3d3c7_44514ad8","line":27,"in_reply_to":"bfb3d3c7_1a197078","updated":"2019-05-20 02:17:43.000000000","message":"I have changed the bp url to file-based-metric-map","commit_id":"137a05230f6330d9c7e398de43cbbee76a10ebea"}],"releasenotes/notes/file-based-metric-map-c2af62b5067895df.yaml":[{"author":{"_account_id":28748,"name":"chenker","email":"chen.ke14@zte.com.cn","username":"chenke"},"change_message_id":"f5e45e64a0cc1334ede898c613573b99440461f1","unresolved":false,"context_lines":[{"line_number":7,"context_line":"    The setting is `watcher_decision_engine/metric_map_path`.  The file"},{"line_number":8,"context_line":"    contains a map per datasource whose keys are the metric names as"},{"line_number":9,"context_line":"    recognized by watcher and the value is the real name of the metric"},{"line_number":10,"context_line":"    in the datasource. This setting defaults to `/etc/watcher/metrc_map.yaml`,"},{"line_number":11,"context_line":"    and presence of this file is optional."}],"source_content_type":"text/x-yaml","patch_set":6,"id":"bfb3d3c7_c4e1ba00","line":10,"range":{"start_line":10,"start_character":61,"end_line":10,"end_character":67},"updated":"2019-05-20 03:01:28.000000000","message":"Missing letter i","commit_id":"137a05230f6330d9c7e398de43cbbee76a10ebea"}],"watcher/conf/decision_engine.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":56,"context_line":"               default\u003d30 * 60,"},{"line_number":57,"context_line":"               mutable\u003dTrue,"},{"line_number":58,"context_line":"               help\u003d\u0027Interval (in seconds) for checking action plan expiry.\u0027),"},{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_c0d66028","line":59,"updated":"2019-05-07 17:05:22.000000000","message":"Should have a release note for this.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":57,"context_line":"               mutable\u003dTrue,"},{"line_number":58,"context_line":"               help\u003d\u0027Interval (in seconds) for checking action plan expiry.\u0027),"},{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_6084540d","line":60,"updated":"2019-05-07 17:05:22.000000000","message":"Why doesn\u0027t this just default to None? It\u0027s optional anyway, and this assumes a default location which deployment tools might not use, i.e. they could use the $state_path config location or $pybasedir. Seems easier to just default this to None (don\u0027t specify a default) and then the code can just check if the option has a value and if so it can check if the file exists and fail if not.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":57,"context_line":"               mutable\u003dTrue,"},{"line_number":58,"context_line":"               help\u003d\u0027Interval (in seconds) for checking action plan expiry.\u0027),"},{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_a54a5052","line":60,"in_reply_to":"dfbec78f_6084540d","updated":"2019-05-09 10:07:32.000000000","message":"With None deployment tools which use this functionality will have write the file and also write its location to the config.\n\nBy putting in a default location, I am allowing the tool to skip step2. And having a default","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"1631d6e57a5d0e180c51d7c4ecddb200f0d40652","unresolved":false,"context_lines":[{"line_number":57,"context_line":"               mutable\u003dTrue,"},{"line_number":58,"context_line":"               help\u003d\u0027Interval (in seconds) for checking action plan expiry.\u0027),"},{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_76739d4e","line":60,"in_reply_to":"dfbec78f_a54a5052","updated":"2019-05-09 14:19:27.000000000","message":"\u003e With None deployment tools which use this functionality will have write the file and also write its location to the config.\n\nAnd that seems like a non-issue to me. If you\u0027re using config management anyway (which everyone should be), then writing the file and configuring where that file lives is trivial.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":58,"context_line":"               help\u003d\u0027Interval (in seconds) for checking action plan expiry.\u0027),"},{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"},{"line_number":64,"context_line":"               \u0027of the metric in the datasource.\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_207e5c19","line":61,"range":{"start_line":61,"start_character":78,"end_line":61,"end_character":79},"updated":"2019-05-07 17:05:22.000000000","message":"here and below you need spaces between lines","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":58,"context_line":"               help\u003d\u0027Interval (in seconds) for checking action plan expiry.\u0027),"},{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"},{"line_number":64,"context_line":"               \u0027of the metric in the datasource.\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_1626e6b8","line":61,"range":{"start_line":61,"start_character":78,"end_line":61,"end_character":79},"in_reply_to":"dfbec78f_207e5c19","updated":"2019-05-09 10:07:32.000000000","message":"Done","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"},{"line_number":64,"context_line":"               \u0027of the metric in the datasource.\u0027)"},{"line_number":65,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_80b5c8cf","line":62,"range":{"start_line":62,"start_character":26,"end_line":62,"end_character":42},"updated":"2019-05-07 17:05:22.000000000","message":"Is this true? What if I only care about overriding some keys on the gnocchi datasource but don\u0027t care about monasca or ceilometer? The processing of the file should handle that gracefully.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"},{"line_number":64,"context_line":"               \u0027of the metric in the datasource.\u0027)"},{"line_number":65,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_d637eee2","line":62,"range":{"start_line":62,"start_character":26,"end_line":62,"end_character":42},"in_reply_to":"dfbec78f_80b5c8cf","updated":"2019-05-09 10:07:32.000000000","message":"Done, the file is optional and allows overriding only mentioned datasources","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"},{"line_number":64,"context_line":"               \u0027of the metric in the datasource.\u0027)"},{"line_number":65,"context_line":"]"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"WATCHER_CONTINUOUS_OPTS \u003d ["}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_c092e04b","line":64,"range":{"start_line":62,"start_character":44,"end_line":64,"end_character":49},"updated":"2019-05-07 17:05:22.000000000","message":"It would be useful to provide an example like from the spec, e.g. you could do something like:\n\nhelp\u003d\n\"\"\"Path to metric map yaml formatted file.\n\nThe file contains a map per datasource whose keys are the metric\nnames as recognized by watcher and the value is the real name of\nthe metric in the datasource. For example::\n\n  monasca:\n    - instance_cpu_usage: VM_CPU\n  gnocchi:\n    - instance_cpu_usage: cpu_vm_util\n\"\"\"","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    cfg.StrOpt(\u0027metric_map_path\u0027,"},{"line_number":60,"context_line":"               default\u003d\u0027/etc/watcher/metric_map.yaml\u0027,"},{"line_number":61,"context_line":"               help\u003d\u0027Path to metric map yaml formatted file. The file contains\u0027"},{"line_number":62,"context_line":"               \u0027a map for every datasource. A map whose keys are the metric\u0027"},{"line_number":63,"context_line":"               \u0027names as recognized by watcher and value is the real name\u0027"},{"line_number":64,"context_line":"               \u0027of the metric in the datasource.\u0027)"},{"line_number":65,"context_line":"]"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"WATCHER_CONTINUOUS_OPTS \u003d ["}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_657698a7","line":64,"range":{"start_line":62,"start_character":44,"end_line":64,"end_character":49},"in_reply_to":"dfbec78f_c092e04b","updated":"2019-05-09 10:07:32.000000000","message":"Good idea about the example, will add this","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"}],"watcher/datasource/manager.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"54e5c3df7de47913297ad16bc7c574b81e60dd49","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            gnoc.GnocchiHelper.NAME: gnoc.GnocchiHelper.METRIC_MAP,"},{"line_number":40,"context_line":"            ceil.CeilometerHelper.NAME: ceil.CeilometerHelper.METRIC_MAP"},{"line_number":41,"context_line":"        }"},{"line_number":42,"context_line":"        metrics_from_file \u003d self.load_metric_map(config.metric_map_path)"},{"line_number":43,"context_line":"        for ds, mp in self.metric_map.items():"},{"line_number":44,"context_line":"            try:"},{"line_number":45,"context_line":"                self.metric_map[ds].update(metrics_from_file.get(ds, {}))"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_405b5053","line":42,"updated":"2019-05-07 17:07:14.000000000","message":"This is blowing up in a job:\n\nhttp://logs.openstack.org/74/657374/4/check/watcher-tempest-basic_optim/346ea0a/controller/logs/screen-watcher-decision-engine.txt.gz\n\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 ERROR watcher.decision_engine.audit.base [req-786dafdb-178c-49d3-9d06-40d3a4f1b73d None None None] metric_map_path: AttributeError: metric_map_path\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base Traceback (most recent call last):\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/audit/base.py\", line 139, in execute\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     solution \u003d self.do_execute(audit, request_context)\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/audit/base.py\", line 83, in do_execute\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     audit, request_context)\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/strategy/context/base.py\", line 45, in execute_strategy\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     solution \u003d self.do_execute_strategy(audit, request_context)\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/strategy/context/default.py\", line 68, in do_execute_strategy\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     return selected_strategy.execute()\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/strategy/strategies/base.py\", line 252, in execute\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     self.do_execute()\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/strategy/strategies/basic_consolidation.py\", line 423, in do_execute\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     scores \u003d self.compute_score_of_nodes()\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/strategy/strategies/basic_consolidation.py\", line 352, in compute_score_of_nodes\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     result \u003d self.calculate_score_node(node)\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/strategy/strategies/basic_consolidation.py\", line 300, in calculate_score_node\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     host_avg_cpu_util \u003d self.get_node_cpu_usage(node)\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/strategy/strategies/basic_consolidation.py\", line 284, in get_node_cpu_usage\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     return self.datasource_backend.get_host_cpu_usage(\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/decision_engine/strategy/strategies/base.py\", line 348, in datasource_backend\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     osc\u003dself.osc\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/datasource/manager.py\", line 42, in __init__\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     metrics_from_file \u003d self.load_metric_map(config.metric_map_path)\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base   File \"/opt/stack/watcher/watcher/common/utils.py\", line 55, in __getattr__\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base     raise AttributeError(name)\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base AttributeError: metric_map_path\nMay 07 11:06:37.763509 ubuntu-bionic-rax-ord-0006012237 watcher-decision-engine[3688]: 2019-05-07 11:06:37.761 3688 ERROR watcher.decision_engine.audit.base","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            gnoc.GnocchiHelper.NAME: gnoc.GnocchiHelper.METRIC_MAP,"},{"line_number":40,"context_line":"            ceil.CeilometerHelper.NAME: ceil.CeilometerHelper.METRIC_MAP"},{"line_number":41,"context_line":"        }"},{"line_number":42,"context_line":"        metrics_from_file \u003d self.load_metric_map(config.metric_map_path)"},{"line_number":43,"context_line":"        for ds, mp in self.metric_map.items():"},{"line_number":44,"context_line":"            try:"},{"line_number":45,"context_line":"                self.metric_map[ds].update(metrics_from_file.get(ds, {}))"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_f6579201","line":42,"in_reply_to":"dfbec78f_405b5053","updated":"2019-05-09 10:07:32.000000000","message":"thanks for spotting. \nI believe the new patchset should fix this","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":45,"context_line":"                self.metric_map[ds].update(metrics_from_file.get(ds, {}))"},{"line_number":46,"context_line":"            except KeyError:"},{"line_number":47,"context_line":"                msgargs \u003d (ds, self.metric_map.keys())"},{"line_number":48,"context_line":"                LOG.info(\u0027Invalid Datasource: %s. Allowed: %s \u0027, *msgargs)"},{"line_number":49,"context_line":"        self.datasources \u003d self.config.datasources"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_600e948e","line":48,"range":{"start_line":48,"start_character":20,"end_line":48,"end_character":24},"updated":"2019-05-07 17:05:22.000000000","message":"This should be at least a warning because the user screwed up the file.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":45,"context_line":"                self.metric_map[ds].update(metrics_from_file.get(ds, {}))"},{"line_number":46,"context_line":"            except KeyError:"},{"line_number":47,"context_line":"                msgargs \u003d (ds, self.metric_map.keys())"},{"line_number":48,"context_line":"                LOG.info(\u0027Invalid Datasource: %s. Allowed: %s \u0027, *msgargs)"},{"line_number":49,"context_line":"        self.datasources \u003d self.config.datasources"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_b6411a3c","line":48,"range":{"start_line":48,"start_character":20,"end_line":48,"end_character":24},"in_reply_to":"dfbec78f_600e948e","updated":"2019-05-09 10:07:32.000000000","message":"Done","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    def ceilometer(self):"},{"line_number":53,"context_line":"        if self._ceilometer is None:"},{"line_number":54,"context_line":"            ds \u003d self.ceilometer \u003d ceil.CeilometerHelper(osc\u003dself.osc)"},{"line_number":55,"context_line":"            ds.METRIC_MAP.update(self.metric_map[ds.NAME])"},{"line_number":56,"context_line":"        return self._ceilometer"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    @ceilometer.setter"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_c0cae018","line":55,"updated":"2019-05-07 17:05:22.000000000","message":"Seems there should be a way to DRY this up since you\u0027re doing it both above and in here per datasource - do you really need this since here if you already did it above and you\u0027re modifying essentially a global mapping per datasource. Should the METRIC_MAP variable in each helper be made into a module-level global? If CeilometerHelper gets created somewhere else in the future it might miss the overrides.\n\nMaybe another alternative is passing the metric map file yaml updates to each helper\u0027s constructor? It just seems like there is some kind of singleton or factory pattern being abused here.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    def ceilometer(self):"},{"line_number":53,"context_line":"        if self._ceilometer is None:"},{"line_number":54,"context_line":"            ds \u003d self.ceilometer \u003d ceil.CeilometerHelper(osc\u003dself.osc)"},{"line_number":55,"context_line":"            ds.METRIC_MAP.update(self.metric_map[ds.NAME])"},{"line_number":56,"context_line":"        return self._ceilometer"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    @ceilometer.setter"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_25abc089","line":55,"in_reply_to":"dfbec78f_c0cae018","updated":"2019-05-09 10:07:32.000000000","message":"I agree with you here that code change begs DRYing but passing these overrides to the constructor is an overkill given that  DataSourceManager is responsible for creating a suitable datasource for needed metrics. \n\nI hope you agree that having metrics (data) hardcoded in sourcecode is itself calling for trouble as it assumes data which it has to control over. \n\nI will try to DRY it out in a different way.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def load_metric_map(self, file_path):"},{"line_number":97,"context_line":"        \"\"\"Load metrics from the config.metric_map_path\"\"\""},{"line_number":98,"context_line":"        if isinstance(file_path, str) and os.path.exists(file_path):"},{"line_number":99,"context_line":"            with open(file_path, \u0027r\u0027) as f:"},{"line_number":100,"context_line":"                try:"},{"line_number":101,"context_line":"                    ret \u003d yaml.safe_load(f.read())"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_60e774e6","line":98,"range":{"start_line":98,"start_character":11,"end_line":98,"end_character":37},"updated":"2019-05-07 17:05:22.000000000","message":"Shouldn\u0027t need this since it\u0027s already a StrOpt. You could just check \"if file_path and ...\".","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def load_metric_map(self, file_path):"},{"line_number":97,"context_line":"        \"\"\"Load metrics from the config.metric_map_path\"\"\""},{"line_number":98,"context_line":"        if isinstance(file_path, str) and os.path.exists(file_path):"},{"line_number":99,"context_line":"            with open(file_path, \u0027r\u0027) as f:"},{"line_number":100,"context_line":"                try:"},{"line_number":101,"context_line":"                    ret \u003d yaml.safe_load(f.read())"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_882ba180","line":98,"range":{"start_line":98,"start_character":11,"end_line":98,"end_character":37},"in_reply_to":"dfbec78f_60e774e6","updated":"2019-05-09 10:07:32.000000000","message":"Done","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":102,"context_line":"                    # return {} if the file is empty"},{"line_number":103,"context_line":"                    return ret if ret else {}"},{"line_number":104,"context_line":"                except yaml.YAMLError as e:"},{"line_number":105,"context_line":"                    LOG.info(\u0027Could not load %s: %s\u0027, file_path, str(e))"},{"line_number":106,"context_line":"                return {}"},{"line_number":107,"context_line":"        else:"},{"line_number":108,"context_line":"            return {}"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_00ef98b0","line":105,"range":{"start_line":105,"start_character":65,"end_line":105,"end_character":71},"updated":"2019-05-07 17:05:22.000000000","message":"You don\u0027t need the str() on this, log parameter substituation will handle that.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":102,"context_line":"                    # return {} if the file is empty"},{"line_number":103,"context_line":"                    return ret if ret else {}"},{"line_number":104,"context_line":"                except yaml.YAMLError as e:"},{"line_number":105,"context_line":"                    LOG.info(\u0027Could not load %s: %s\u0027, file_path, str(e))"},{"line_number":106,"context_line":"                return {}"},{"line_number":107,"context_line":"        else:"},{"line_number":108,"context_line":"            return {}"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_c5a744a7","line":105,"range":{"start_line":105,"start_character":65,"end_line":105,"end_character":71},"in_reply_to":"dfbec78f_00ef98b0","updated":"2019-05-09 10:07:32.000000000","message":"Done","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":105,"context_line":"                    LOG.info(\u0027Could not load %s: %s\u0027, file_path, str(e))"},{"line_number":106,"context_line":"                return {}"},{"line_number":107,"context_line":"        else:"},{"line_number":108,"context_line":"            return {}"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_60353446","line":108,"updated":"2019-05-07 17:05:22.000000000","message":"If you remove the default (as suggested) and then a file path is specified but doesn\u0027t exist, wouldn\u0027t you want to log something for that here?","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":105,"context_line":"                    LOG.info(\u0027Could not load %s: %s\u0027, file_path, str(e))"},{"line_number":106,"context_line":"                return {}"},{"line_number":107,"context_line":"        else:"},{"line_number":108,"context_line":"            return {}"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_36776aa3","line":108,"in_reply_to":"dfbec78f_60353446","updated":"2019-05-09 10:07:32.000000000","message":"let me know if you dont like the new approach","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":21692,"name":"licanwei","email":"li.canwei2@zte.com.cn","username":"licanwei"},"change_message_id":"c5fdbff2653b1ad7b18ce01ae5c01b48dbbc6d47","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        metrics_from_file \u003d self.load_metric_map(metric_map_path)"},{"line_number":45,"context_line":"        for ds, mp in self.metric_map.items():"},{"line_number":46,"context_line":"            try:"},{"line_number":47,"context_line":"                self.metric_map[ds].update(metrics_from_file.get(ds, {}))"},{"line_number":48,"context_line":"            except KeyError:"},{"line_number":49,"context_line":"                msgargs \u003d (ds, self.metric_map.keys())"},{"line_number":50,"context_line":"                LOG.warning(\u0027Invalid Datasource: %s. Allowed: %s \u0027, *msgargs)"}],"source_content_type":"text/x-python","patch_set":5,"id":"dfbec78f_70e71414","line":47,"range":{"start_line":47,"start_character":16,"end_line":47,"end_character":73},"updated":"2019-05-10 06:26:39.000000000","message":"If metrics_from_file is {}, we should keep self.metric_map with its default value.","commit_id":"4f44e4bbc128f5b6ad51edec3843609b37506ff3"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"e5a01a624c7e248529cb16b0e81d073ce82dd4d4","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        metrics_from_file \u003d self.load_metric_map(metric_map_path)"},{"line_number":45,"context_line":"        for ds, mp in self.metric_map.items():"},{"line_number":46,"context_line":"            try:"},{"line_number":47,"context_line":"                self.metric_map[ds].update(metrics_from_file.get(ds, {}))"},{"line_number":48,"context_line":"            except KeyError:"},{"line_number":49,"context_line":"                msgargs \u003d (ds, self.metric_map.keys())"},{"line_number":50,"context_line":"                LOG.warning(\u0027Invalid Datasource: %s. Allowed: %s \u0027, *msgargs)"}],"source_content_type":"text/x-python","patch_set":5,"id":"dfbec78f_fa2e7ef8","line":47,"range":{"start_line":47,"start_character":16,"end_line":47,"end_character":73},"in_reply_to":"dfbec78f_70e71414","updated":"2019-05-10 09:38:00.000000000","message":"If metrics_from_file is {}, then metrics_from_file.get will return {}, so update will not change anything","commit_id":"4f44e4bbc128f5b6ad51edec3843609b37506ff3"}],"watcher/tests/datasource/test_manager.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from mock import MagicMock"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from watcher.common import exception"},{"line_number":22,"context_line":"from watcher.datasource.manager import DataSourceManager"},{"line_number":23,"context_line":"from watcher.datasource import monasca as mon"},{"line_number":24,"context_line":"from watcher.tests import base"},{"line_number":25,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_80bb8870","line":22,"updated":"2019-05-07 17:05:22.000000000","message":"I\u0027m pretty sure this is a pep8 issue somewhere since you should only import modules not classes.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from mock import MagicMock"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from watcher.common import exception"},{"line_number":22,"context_line":"from watcher.datasource.manager import DataSourceManager"},{"line_number":23,"context_line":"from watcher.datasource import monasca as mon"},{"line_number":24,"context_line":"from watcher.tests import base"},{"line_number":25,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_85094c96","line":22,"in_reply_to":"dfbec78f_80bb8870","updated":"2019-05-09 10:07:32.000000000","message":"I am sorry, but that is not the case.\nhttps://www.python.org/dev/peps/pep-0008/#id23 here is says `from subprocess import Popen, PIPE` which are classes","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7bbafc41ccc7538755c17a707bfac8f3ea5fe772","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from mock import MagicMock"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from watcher.common import exception"},{"line_number":22,"context_line":"from watcher.datasource.manager import DataSourceManager"},{"line_number":23,"context_line":"from watcher.datasource import monasca as mon"},{"line_number":24,"context_line":"from watcher.tests import base"},{"line_number":25,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_769abd6e","line":22,"in_reply_to":"dfbec78f_85094c96","updated":"2019-05-09 14:18:25.000000000","message":"Sorry I said pep8 but was thinking hacking:\n\nhttps://docs.openstack.org/hacking/latest/user/hacking.html#imports\n\nMaybe watcher isn\u0027t using the hacking library.","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        mo.return_value \u003d {"},{"line_number":60,"context_line":"            mon.MonascaHelper.NAME: {\"host_airflow\": \"host_fan_speed\"}"},{"line_number":61,"context_line":"        }"},{"line_number":62,"context_line":"        real_fn \u003d DataSourceManager.load_metric_map"},{"line_number":63,"context_line":"        DataSourceManager.load_metric_map \u003d mo"},{"line_number":64,"context_line":"        manager \u003d DataSourceManager("},{"line_number":65,"context_line":"            config\u003dMagicMock(datasources\u003d[\u0027monasca\u0027]),"},{"line_number":66,"context_line":"            osc\u003dMagicMock()"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_e0ab641a","line":63,"range":{"start_line":62,"start_character":8,"end_line":63,"end_character":46},"updated":"2019-05-07 17:05:22.000000000","message":"You shouldn\u0027t need L68 if you use a mock with side_effect or return_value for the load_metric_map function:\n\nwith mock.patch(\u0027watcher.datasource.manager.DataSourceManager.load_metric_map\u0027,\n                return_value\u003dmo):\n    manager \u003d DataSourceManager(\n            config\u003dMagicMock(datasources\u003d[\u0027monasca\u0027]),\n            osc\u003dMagicMock())","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        mo.return_value \u003d {"},{"line_number":60,"context_line":"            mon.MonascaHelper.NAME: {\"host_airflow\": \"host_fan_speed\"}"},{"line_number":61,"context_line":"        }"},{"line_number":62,"context_line":"        real_fn \u003d DataSourceManager.load_metric_map"},{"line_number":63,"context_line":"        DataSourceManager.load_metric_map \u003d mo"},{"line_number":64,"context_line":"        manager \u003d DataSourceManager("},{"line_number":65,"context_line":"            config\u003dMagicMock(datasources\u003d[\u0027monasca\u0027]),"},{"line_number":66,"context_line":"            osc\u003dMagicMock()"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_2546607e","line":63,"range":{"start_line":62,"start_character":8,"end_line":63,"end_character":46},"in_reply_to":"dfbec78f_e0ab641a","updated":"2019-05-09 10:07:32.000000000","message":"Done","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"268a833c8469ce8a10ce3f4e438a0cdec4ba3441","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        with mock.patch(\u0027yaml.safe_load\u0027) as mo:"},{"line_number":74,"context_line":"            mo.return_value \u003d {\"newds\": {\"metric_one\": \"i_am_metric_one\"}}"},{"line_number":75,"context_line":"            manager \u003d DataSourceManager(config\u003dMagicMock(), osc\u003dMagicMock())"},{"line_number":76,"context_line":"            self.assertFalse(\u0027newds\u0027 in manager.metric_map.keys())"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_606d3403","line":76,"range":{"start_line":76,"start_character":17,"end_line":76,"end_character":28},"updated":"2019-05-07 17:05:22.000000000","message":"use assertNotIn","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"15ea0b7f668f2f1caa3f49e0329d97c5f33553dd","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        with mock.patch(\u0027yaml.safe_load\u0027) as mo:"},{"line_number":74,"context_line":"            mo.return_value \u003d {\"newds\": {\"metric_one\": \"i_am_metric_one\"}}"},{"line_number":75,"context_line":"            manager \u003d DataSourceManager(config\u003dMagicMock(), osc\u003dMagicMock())"},{"line_number":76,"context_line":"            self.assertFalse(\u0027newds\u0027 in manager.metric_map.keys())"}],"source_content_type":"text/x-python","patch_set":4,"id":"dfbec78f_852e2cf8","line":76,"range":{"start_line":76,"start_character":17,"end_line":76,"end_character":28},"in_reply_to":"dfbec78f_606d3403","updated":"2019-05-09 10:07:32.000000000","message":"Done","commit_id":"df76dfde60ed7aea05a906f69100cf57fc4093b2"},{"author":{"_account_id":21692,"name":"licanwei","email":"li.canwei2@zte.com.cn","username":"licanwei"},"change_message_id":"c5fdbff2653b1ad7b18ce01ae5c01b48dbbc6d47","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        self.assertRaises(exception.NoSuchMetric, manager.get_backend,"},{"line_number":56,"context_line":"                          [\u0027host_cpu\u0027, \u0027instance_cpu_usage\u0027])"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def test_metric_file_path_not_exists(self):"},{"line_number":59,"context_line":"        manager \u003d DataSourceManager(config\u003dself._get_config(), osc\u003dMagicMock())"},{"line_number":60,"context_line":"        self.assertEqual({}, manager.load_metric_map(\u0027/nope/nope/nope.yaml\u0027))"},{"line_number":61,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"dfbec78f_b0b6ecf9","line":58,"range":{"start_line":58,"start_character":8,"end_line":58,"end_character":40},"updated":"2019-05-10 06:26:39.000000000","message":"We also should check self.metric_map, it should have default value.","commit_id":"4f44e4bbc128f5b6ad51edec3843609b37506ff3"},{"author":{"_account_id":23735,"name":"sumitjami","email":"sjamgade@suse.com","username":"nthforloop"},"change_message_id":"e5a01a624c7e248529cb16b0e81d073ce82dd4d4","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        self.assertRaises(exception.NoSuchMetric, manager.get_backend,"},{"line_number":56,"context_line":"                          [\u0027host_cpu\u0027, \u0027instance_cpu_usage\u0027])"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def test_metric_file_path_not_exists(self):"},{"line_number":59,"context_line":"        manager \u003d DataSourceManager(config\u003dself._get_config(), osc\u003dMagicMock())"},{"line_number":60,"context_line":"        self.assertEqual({}, manager.load_metric_map(\u0027/nope/nope/nope.yaml\u0027))"},{"line_number":61,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"dfbec78f_7af5ae82","line":58,"range":{"start_line":58,"start_character":8,"end_line":58,"end_character":40},"in_reply_to":"dfbec78f_b0b6ecf9","updated":"2019-05-10 09:38:00.000000000","message":"Done","commit_id":"4f44e4bbc128f5b6ad51edec3843609b37506ff3"}],"watcher/tests/datasources/test_manager.py":[{"author":{"_account_id":28748,"name":"chenker","email":"chen.ke14@zte.com.cn","username":"chenke"},"change_message_id":"f5e45e64a0cc1334ede898c613573b99440461f1","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        manager \u003d self._dsm()"},{"line_number":67,"context_line":"        expected \u003d ds_manager.DataSourceManager.metric_map"},{"line_number":68,"context_line":"        actual \u003d manager.metric_map"},{"line_number":69,"context_line":"        self.assertEqual(actual, expected)"},{"line_number":70,"context_line":"        self.assertEqual({}, manager.load_metric_map(\u0027/nope/nope/nope.yaml\u0027))"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def test_metric_file_metric_override(self):"}],"source_content_type":"text/x-python","patch_set":6,"id":"bfb3d3c7_e4bb9ee2","line":69,"range":{"start_line":69,"start_character":33,"end_line":69,"end_character":41},"updated":"2019-05-20 03:01:28.000000000","message":"I suggest this Line :self.assertEqual(expected, actual)","commit_id":"137a05230f6330d9c7e398de43cbbee76a10ebea"},{"author":{"_account_id":28748,"name":"chenker","email":"chen.ke14@zte.com.cn","username":"chenke"},"change_message_id":"f5e45e64a0cc1334ede898c613573b99440461f1","unresolved":false,"context_lines":[{"line_number":78,"context_line":"            dsmcfg \u003d self._dsm_config(datasources\u003d[\u0027monasca\u0027])"},{"line_number":79,"context_line":"            manager \u003d self._dsm(config\u003ddsmcfg)"},{"line_number":80,"context_line":"            backend \u003d manager.get_backend([\u0027host_cpu_usage\u0027])"},{"line_number":81,"context_line":"            self.assertEqual(backend.METRIC_MAP[\u0027host_airflow\u0027], \"host_fnspid\")"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    def test_metric_file_invalid_ds(self):"},{"line_number":84,"context_line":"        with mock.patch(\u0027yaml.safe_load\u0027) as mo:"}],"source_content_type":"text/x-python","patch_set":6,"id":"bfb3d3c7_04c11255","line":81,"range":{"start_line":81,"start_character":11,"end_line":81,"end_character":79},"updated":"2019-05-20 03:01:28.000000000","message":"ditto","commit_id":"137a05230f6330d9c7e398de43cbbee76a10ebea"}]}
