added rackspace maas format (#28)
Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
This commit is contained in:
parent
775f034a78
commit
a61786d4e1
|
@ -82,7 +82,8 @@ class MonitorStackCLI(click.MultiCommand):
|
||||||
VALID_OUTPUT_FORMATS = [
|
VALID_OUTPUT_FORMATS = [
|
||||||
'json',
|
'json',
|
||||||
'line',
|
'line',
|
||||||
'telegraf'
|
'telegraf',
|
||||||
|
'rax-maas'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +108,7 @@ def cli(ctx, output_format, verbose):
|
||||||
def process_result(result, output_format, verbose):
|
def process_result(result, output_format, verbose):
|
||||||
"""Render the output into the proper format."""
|
"""Render the output into the proper format."""
|
||||||
module_name = 'monitorstack.common.formatters'
|
module_name = 'monitorstack.common.formatters'
|
||||||
method_name = 'write_{}'.format(output_format)
|
method_name = 'write_{}'.format(output_format.replace('-', '_'))
|
||||||
output_formatter = getattr(
|
output_formatter = getattr(
|
||||||
importlib.import_module(module_name),
|
importlib.import_module(module_name),
|
||||||
method_name
|
method_name
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
"""Output methods."""
|
"""Output methods."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -38,18 +39,62 @@ def _current_time():
|
||||||
return int(time.time() * 1000000000)
|
return int(time.time() * 1000000000)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_value_types(value, measurement_type=None):
|
||||||
|
"""Return the value and the measurement type.
|
||||||
|
|
||||||
|
This method will evaluate a given value and cast it to the
|
||||||
|
appropriate type. If the parameter `measurement_type` is
|
||||||
|
not provided the method will assign the type based on the
|
||||||
|
key set in the types list.
|
||||||
|
|
||||||
|
:param value: item to evaluate.
|
||||||
|
:param measurement_type: name of the measurement
|
||||||
|
"""
|
||||||
|
def _check_value(c_type, c_value):
|
||||||
|
try:
|
||||||
|
c_value = c_type(c_value)
|
||||||
|
except ValueError:
|
||||||
|
return False, c_value
|
||||||
|
else:
|
||||||
|
return True, c_value
|
||||||
|
|
||||||
|
success = False
|
||||||
|
if isinstance(value, str) and '.' in value:
|
||||||
|
success, value = _check_value(
|
||||||
|
c_type=float,
|
||||||
|
c_value=value
|
||||||
|
)
|
||||||
|
|
||||||
|
elif isinstance(value, float):
|
||||||
|
success = True
|
||||||
|
|
||||||
|
if success:
|
||||||
|
_measurement_type = 'float'
|
||||||
|
else:
|
||||||
|
_, value = _check_value(
|
||||||
|
c_type=int,
|
||||||
|
c_value=value
|
||||||
|
)
|
||||||
|
if isinstance(value, int):
|
||||||
|
if value > 2147483647:
|
||||||
|
_measurement_type = 'int64'
|
||||||
|
else:
|
||||||
|
_measurement_type = 'int32'
|
||||||
|
else:
|
||||||
|
_measurement_type = 'string'
|
||||||
|
|
||||||
|
if not measurement_type:
|
||||||
|
measurement_type = _measurement_type
|
||||||
|
|
||||||
|
return value, measurement_type
|
||||||
|
|
||||||
|
|
||||||
def _telegraf_line_format(sets, quote=False):
|
def _telegraf_line_format(sets, quote=False):
|
||||||
"""Return a comma separated string."""
|
"""Return a comma separated string."""
|
||||||
store = list()
|
store = list()
|
||||||
for k, v in sets.items():
|
for k, v in sets.items():
|
||||||
k = k.replace(' ', '_')
|
k = k.replace(' ', '_')
|
||||||
for v_type in [int, float]:
|
v, _ = _get_value_types(value=v)
|
||||||
try:
|
|
||||||
v = v_type(v)
|
|
||||||
except ValueError:
|
|
||||||
pass # v was not a int, float, or long
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
if not isinstance(v, (int, float, bool)) and quote:
|
if not isinstance(v, (int, float, bool)) and quote:
|
||||||
store.append('{}="{}"'.format(k, v))
|
store.append('{}="{}"'.format(k, v))
|
||||||
else:
|
else:
|
||||||
|
@ -72,3 +117,27 @@ def write_telegraf(result):
|
||||||
click.echo(' '.join(resultant))
|
click.echo(' '.join(resultant))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def write_rax_maas(result):
|
||||||
|
"""Output in Rackspace Monitoring as a Service format."""
|
||||||
|
status = ['status']
|
||||||
|
if result['exit_code'] == 0:
|
||||||
|
status.append('okay')
|
||||||
|
else:
|
||||||
|
status.append('error')
|
||||||
|
|
||||||
|
status.append(result['message'])
|
||||||
|
click.echo(' '.join(status))
|
||||||
|
|
||||||
|
for key, value in result['variables'].items():
|
||||||
|
value, measurement_type = _get_value_types(
|
||||||
|
value=value,
|
||||||
|
measurement_type=result.get('measurement_type')
|
||||||
|
)
|
||||||
|
metric = ['metric', key, measurement_type, str(value)]
|
||||||
|
if 'measurement_units' in result:
|
||||||
|
metric.append(result['measurement_units'])
|
||||||
|
click.echo(' '.join(metric))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
|
@ -28,6 +28,40 @@ SAMPLE_RESULT = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SAMPLE_RESULT_ERROR = {
|
||||||
|
'exit_code': 1,
|
||||||
|
'message': 'uptime failed',
|
||||||
|
'measurement_name': 'system_uptime',
|
||||||
|
'meta': {},
|
||||||
|
'variables': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
SAMPLE_RESULT_MEASUREMENT_TYPE = {
|
||||||
|
'exit_code': 0,
|
||||||
|
'message': 'uptime is ok',
|
||||||
|
'measurement_name': 'system_uptime',
|
||||||
|
'measurement_type': 'testType',
|
||||||
|
'meta': {
|
||||||
|
'platform': 'example_platform',
|
||||||
|
},
|
||||||
|
'variables': {
|
||||||
|
'uptime': '29587.75'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SAMPLE_RESULT_MEASUREMENT_UNITS = {
|
||||||
|
'exit_code': 0,
|
||||||
|
'message': 'uptime is ok',
|
||||||
|
'measurement_name': 'system_uptime',
|
||||||
|
'measurement_units': 'testUnits',
|
||||||
|
'meta': {
|
||||||
|
'platform': 'example_platform',
|
||||||
|
},
|
||||||
|
'variables': {
|
||||||
|
'uptime': '29587.75'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SAMPLE_RESULT_NO_META = {
|
SAMPLE_RESULT_NO_META = {
|
||||||
'exit_code': 0,
|
'exit_code': 0,
|
||||||
'message': 'uptime is ok',
|
'message': 'uptime is ok',
|
||||||
|
@ -56,6 +90,54 @@ class TestFormatters(object):
|
||||||
assert isinstance(result, int)
|
assert isinstance(result, int)
|
||||||
assert result > 0
|
assert result > 0
|
||||||
|
|
||||||
|
def test__get_value_types_int32(self):
|
||||||
|
"""Test _get_value_types() with int."""
|
||||||
|
value, m_type = formatters._get_value_types(1)
|
||||||
|
assert value == 1
|
||||||
|
assert m_type == 'int32'
|
||||||
|
|
||||||
|
def test__get_value_types_int32_str(self):
|
||||||
|
"""Test _get_value_types() with int."""
|
||||||
|
value, m_type = formatters._get_value_types('1')
|
||||||
|
assert value == 1
|
||||||
|
assert m_type == 'int32'
|
||||||
|
|
||||||
|
def test__get_value_types_int64(self):
|
||||||
|
"""Test _get_value_types() with int."""
|
||||||
|
value, m_type = formatters._get_value_types(9999999999)
|
||||||
|
assert value == 9999999999
|
||||||
|
assert m_type == 'int64'
|
||||||
|
|
||||||
|
def test__get_value_types_int64_str(self):
|
||||||
|
"""Test _get_value_types() with int."""
|
||||||
|
value, m_type = formatters._get_value_types('9999999999')
|
||||||
|
assert value == 9999999999
|
||||||
|
assert m_type == 'int64'
|
||||||
|
|
||||||
|
def test__get_value_types_float(self):
|
||||||
|
"""Test _get_value_types() with float."""
|
||||||
|
value, m_type = formatters._get_value_types(1.1)
|
||||||
|
assert value == 1.1
|
||||||
|
assert m_type == 'float'
|
||||||
|
|
||||||
|
def test__get_value_types_float_str(self):
|
||||||
|
"""Test _get_value_types() with float."""
|
||||||
|
value, m_type = formatters._get_value_types('1.1')
|
||||||
|
assert value == 1.1
|
||||||
|
assert m_type == 'float'
|
||||||
|
|
||||||
|
def test__get_value_types_set_m_type(self):
|
||||||
|
"""Test _get_value_types() with float."""
|
||||||
|
value, m_type = formatters._get_value_types('1.1', 'double')
|
||||||
|
assert value == 1.1
|
||||||
|
assert m_type == 'double'
|
||||||
|
|
||||||
|
def test__get_value_types_string(self):
|
||||||
|
"""Test _get_value_types() with str."""
|
||||||
|
value, m_type = formatters._get_value_types('TestString')
|
||||||
|
assert value == 'TestString'
|
||||||
|
assert m_type == 'string'
|
||||||
|
|
||||||
def test_write_json(self, capsys):
|
def test_write_json(self, capsys):
|
||||||
"""Test write_json() module."""
|
"""Test write_json() module."""
|
||||||
formatters.write_json(SAMPLE_RESULT)
|
formatters.write_json(SAMPLE_RESULT)
|
||||||
|
@ -95,3 +177,32 @@ class TestFormatters(object):
|
||||||
assert isinstance(result, str)
|
assert isinstance(result, str)
|
||||||
assert 'othervar=3' in result
|
assert 'othervar=3' in result
|
||||||
assert 'platform="example_platform"' in result
|
assert 'platform="example_platform"' in result
|
||||||
|
|
||||||
|
def test_write_rax_maas(self, capsys):
|
||||||
|
"""Test write_telegraf() module."""
|
||||||
|
formatters.write_rax_maas(SAMPLE_RESULT)
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
assert SAMPLE_RESULT['message'] in out
|
||||||
|
assert 'metric uptime float 29587.75' in out
|
||||||
|
|
||||||
|
def test_write_rax_maas_with_types(self, capsys):
|
||||||
|
"""Test write_telegraf() module."""
|
||||||
|
formatters.write_rax_maas(SAMPLE_RESULT_MEASUREMENT_TYPE)
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
assert SAMPLE_RESULT['message'] in out
|
||||||
|
assert 'metric uptime testType 29587.75' in out
|
||||||
|
|
||||||
|
def test_write_rax_maas_with_units(self, capsys):
|
||||||
|
"""Test write_telegraf() module."""
|
||||||
|
formatters.write_rax_maas(SAMPLE_RESULT_MEASUREMENT_UNITS)
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
out_split = out.splitlines()
|
||||||
|
assert [i for i in out_split if SAMPLE_RESULT['message'] in i]
|
||||||
|
assert 'metric uptime float 29587.75 testUnits' in out_split
|
||||||
|
|
||||||
|
def test_write_rax_maas_with_error(self, capsys):
|
||||||
|
"""Test write_telegraf() module."""
|
||||||
|
formatters.write_rax_maas(SAMPLE_RESULT_ERROR)
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
out_split = out.splitlines()
|
||||||
|
assert [i for i in out_split if 'status error' in i]
|
||||||
|
|
Loading…
Reference in New Issue