Increase usefulness of Agent diagnostic commands

This update adds the following:
 - Added color and error-resolving hints to 'monasca-forwarder info'
 - Made 'monasca-collector check <checkname>' output more human-readable
 - Added 'monasca-collector check_all' parameter to run all configured checks

Change-Id: I752eeddebc0bdd47a515d4af5affb6d850b44b0d
This commit is contained in:
David Schroeder 2014-07-28 10:18:19 -06:00
parent 4c7301570c
commit 178509a3aa
3 changed files with 56 additions and 10 deletions

View File

@ -3,6 +3,9 @@
If you are writing your own checks you should subclass the AgentCheck class. If you are writing your own checks you should subclass the AgentCheck class.
The Check class is being deprecated so don't write new checks with it. The Check class is being deprecated so don't write new checks with it.
""" """
# This file uses 'print' as a function rather than a statement, a la Python3
from __future__ import print_function
import logging import logging
import os import os
from pprint import pprint from pprint import pprint
@ -19,7 +22,8 @@ from monagent.common.util import LaconicFilter, get_hostname, get_os
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# todo convert all checks to the new interface then remove this. Is the LaconicFilter on logs used elsewhere? # todo convert all checks to the new interface then remove this.
# Is the LaconicFilter on logs used elsewhere?
# ============================================================================== # ==============================================================================
# DEPRECATED # DEPRECATED
# ------------------------------ # ------------------------------
@ -235,7 +239,8 @@ class Check(object):
This is the preferred method to retrieve metrics This is the preferred method to retrieve metrics
@return the list of samples @return the list of samples
@rtype [(metric_name, timestamp, value, {"dimensions": {"name1": "key1", "name2": "key2"}}), ...] @rtype [(metric_name, timestamp, value,
{"dimensions": {"name1": "key1", "name2": "key2"}}), ...]
""" """
metrics = [] metrics = []
for m in self._sample_store: for m in self._sample_store:
@ -258,6 +263,8 @@ class Check(object):
metrics.append((m, int(ts), val, attributes)) metrics.append((m, int(ts), val, attributes))
except Exception: except Exception:
pass pass
if prettyprint:
print("Metrics: {}".format(metrics))
return metrics return metrics
@ -413,13 +420,27 @@ class AgentCheck(object):
""" """
return len(self.events) > 0 return len(self.events) > 0
def get_metrics(self): def get_metrics(self, prettyprint=False):
""" """
Get all metrics, including the ones that are tagged. Get all metrics, including the ones that are tagged.
@return the list of samples @return the list of samples
@rtype list of Measurement objects from monagent.common.metrics @rtype list of Measurement objects from monagent.common.metrics
""" """
if prettyprint:
metrics = self.aggregator.flush()
for metric in metrics:
print(" Timestamp: {}".format(metric.timestamp))
print(" Name: {}".format(metric.name))
print(" Value: {}".format(metric.value))
print(" Dimensions: ", end='')
line = 0
for name in metric.dimensions:
if line != 0:
print(" " * 13, end='')
print("{0}={1}".format(name, metric.dimensions[name]))
line += 1
print("-" * 24)
return self.aggregator.flush() return self.aggregator.flush()
def get_events(self): def get_events(self):

View File

@ -15,15 +15,15 @@ import sys
import time import time
import glob import glob
# Check we're not using an old version of Python. We need 2.4 above because some modules (like subprocess) # Check we're not using an old version of Python. We need 2.4 above because
# were only introduced in 2.4. # some modules (like subprocess) were only introduced in 2.4.
if int(sys.version_info[1]) <= 3: if int(sys.version_info[1]) <= 3:
sys.stderr.write("Monasca Agent requires python 2.4 or later.\n") sys.stderr.write("Monasca Agent requires python 2.4 or later.\n")
sys.exit(2) sys.exit(2)
# Custom modules # Custom modules
from checks.collector import Collector from checks.collector import Collector
from monagent.common.check_status import CollectorStatus from monagent.common.check_status import CollectorStatus, ForwarderStatus
from monagent.common.config import get_config, get_parsed_args, load_check_directory, get_confd_path, check_yaml, get_logging_config from monagent.common.config import get_config, get_parsed_args, load_check_directory, get_confd_path, check_yaml, get_logging_config
from monagent.common.daemon import Daemon, AgentSupervisor from monagent.common.daemon import Daemon, AgentSupervisor
from monagent.common.emitter import http_emitter from monagent.common.emitter import http_emitter
@ -193,6 +193,7 @@ def main():
'status', 'status',
'info', 'info',
'check', 'check',
'check_all',
'configcheck', 'configcheck',
'jmx', 'jmx',
] ]
@ -262,14 +263,26 @@ def main():
for check in checks['initialized_checks']: for check in checks['initialized_checks']:
if check.name == check_name: if check.name == check_name:
check.run() check.run()
print(check.get_metrics()) print("Metrics: ")
print(check.get_events()) check.get_metrics(prettyprint=True)
if len(args) == 3 and args[2] == 'check_rate': if len(args) == 3 and args[2] == 'check_rate':
print("Running 2nd iteration to capture rate metrics") print("Running 2nd iteration to capture rate metrics")
time.sleep(1) time.sleep(1)
check.run() check.run()
print(check.get_metrics()) print("Metrics: ")
print(check.get_events()) check.get_metrics(prettyprint=True)
elif 'check_all' == command:
print("Loading check directory...")
checks = load_check_directory(agentConfig)
print("...directory loaded.\n")
for check in checks['initialized_checks']:
print("#" * 80)
print("Check name: '{}'\n".format(check.name))
check.run()
print("Metrics: ")
check.get_metrics(prettyprint=True)
print("#" * 80 + "\n\n")
elif 'configcheck' == command or 'configtest' == command: elif 'configcheck' == command or 'configtest' == command:
osname = get_os() osname = get_os()

View File

@ -571,6 +571,18 @@ class ForwarderStatus(AgentStatus):
"Transactions received: %s" % self.transactions_received, "Transactions received: %s" % self.transactions_received,
"Transactions flushed: %s" % self.transactions_flushed "Transactions flushed: %s" % self.transactions_flushed
] ]
if self.transactions_flushed == 0:
lines.append("[%s]: Unable to flush transactions\n %s" %
(style(STATUS_ERROR, 'red'),
"Please verify monasca-api is running as configured"))
elif self.transactions_flushed != self.transactions_received:
lines.append("[%s]: Transactions out of sync\n %s" %
(style(STATUS_WARNING, 'yellow'),
"Likely contact interruption with monasca-api"))
else:
lines.append("[%s]: Transactions up to date" %
style(STATUS_OK, 'green'))
return lines return lines
def has_error(self): def has_error(self):