Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion disk/datadog_checks/disk/disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from datadog_checks.base import AgentCheck, ConfigurationError, is_affirmative
from datadog_checks.base.utils.platform import Platform
from datadog_checks.base.utils.subprocess_output import get_subprocess_output
from datadog_checks.base.utils.subprocess_output import SubprocessOutputEmptyError, get_subprocess_output
from datadog_checks.base.utils.timeout import TimeoutException, timeout

try:
Expand Down Expand Up @@ -70,6 +70,8 @@ def __init__(self, name, init_config, agentConfig, instances=None):
self._compile_pattern_filters(instance)
self._compile_tag_re()

self.devices_label = {}

def _load_legacy_option(self, instance, option, default, legacy_name=None, operation=lambda l: l):
value = instance.get(option, default)
legacy_name = legacy_name or option
Expand All @@ -85,6 +87,8 @@ def _load_legacy_option(self, instance, option, default, legacy_name=None, opera

def check(self, instance):
"""Get disk space/inode stats"""
if Platform.is_linux():
self.devices_label = self._get_devices_label()
# Windows and Mac will always have psutil
# (we have packaged for both of them)
if self._psutil():
Expand Down Expand Up @@ -134,6 +138,9 @@ def collect_metrics_psutil(self):
if regex.match(device_name):
tags.extend(device_tags)

if self.devices_label.get(device_name):
tags.append(self.devices_label.get(device_name))

# legacy check names c: vs psutil name C:\\
if Platform.is_win32():
device_name = device_name.strip('\\').lower()
Expand Down Expand Up @@ -308,6 +315,10 @@ def collect_metrics_manually(self):
if regex.match(device_name):
tags += device_tags
tags.append('device:{}'.format(device_name))

if self.devices_label.get(device_name):
tags.append(self.devices_label.get(device_name))

for metric_name, value in iteritems(self._collect_metrics_manually(device)):
self.gauge(metric_name, value, tags=tags)

Expand Down Expand Up @@ -455,3 +466,26 @@ def _compile_tag_re(self):
except TypeError:
self.log.warning('{} is not a valid regular expression and will be ignored'.format(regex_str))
self._device_tag_re = device_tag_list

def _get_devices_label(self):
"""
Get every label to create tags
"""
devices_label = {}
try:
blkid_out, _, _ = get_subprocess_output(['blkid'], self.log)
all_devices = [l.strip().split() for l in blkid_out.splitlines()]
Comment thread
coignetp marked this conversation as resolved.
Outdated

for d in all_devices:
# Line sample
# /dev/sda1: LABEL="MYLABEL" UUID="5eea373d-db36-4ce2-8c71-12ce544e8559" TYPE="ext4"
for att in d:
if att.startswith('LABEL='):
# Removing ':' from the name
device_name = d[0].rstrip(':')
Comment thread
coignetp marked this conversation as resolved.
Outdated
devices_label[device_name] = "label:{}".format(att.split('=')[1].strip('"'))

except SubprocessOutputEmptyError:
self.log.debug("Couldn't use blkid to have device labels")

return devices_label
3 changes: 3 additions & 0 deletions disk/tests/fixtures/blkid
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/dev/sda1: UUID="9RbyZC-LtBG-J6RS-EH7g-wYMT-wQP2-wftnVi" TYPE="LVM2_member" PARTUUID="1e4b9125-01"
/dev/mapper/vagrant--vg-root: LABEL="DATA" UUID="5eea373d-db36-4ce2-8c71-12ce544e8559" TYPE="ext4"
/dev/mapper/vagrant--vg-swap_1: UUID="1678c43d-0654-4c4a-87f1-90dffa21ed34" TYPE="swap"
9 changes: 9 additions & 0 deletions disk/tests/mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ def mock_df_output(fname):
return f.read(), '', ''


def mock_blkid_output():
"""
Load fixtures from tests/fixtures/ folder and return a tuple matching the
return value of `get_subprocess_output`
"""
with open(os.path.join(HERE, 'fixtures', 'blkid')) as f:
return f.read(), '', ''


class MockPart(object):
def __init__(
self, device=DEFAULT_DEVICE_NAME, fstype=DEFAULT_FILE_SYSTEM, mountpoint=DEFAULT_MOUNT_POINT, opts='ro'
Expand Down
40 changes: 32 additions & 8 deletions disk/tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from datadog_checks.disk import Disk

from .common import DEFAULT_DEVICE_NAME, DEFAULT_FILE_SYSTEM, DEFAULT_MOUNT_POINT
from .mocks import MockInodesMetrics, mock_df_output
from .mocks import MockInodesMetrics, mock_blkid_output, mock_df_output
from .utils import requires_unix


Expand Down Expand Up @@ -61,19 +61,25 @@ def test_psutil(aggregator, gauge_metrics, rate_metrics):
c.check(instance)

if tag_by == 'true':
tags = [
gauge_tags = [
DEFAULT_FILE_SYSTEM,
'filesystem:{}'.format(DEFAULT_FILE_SYSTEM),
'device:{}'.format(DEFAULT_DEVICE_NAME),
]
else:
tags = []
gauge_tags = []

rate_tags = ['device:{}'.format(DEFAULT_DEVICE_NAME)]

if c.devices_label.get(DEFAULT_DEVICE_NAME):
gauge_tags.append(c.devices_label.get(DEFAULT_DEVICE_NAME))
rate_tags.append(c.devices_label.get(DEFAULT_DEVICE_NAME))

for name, value in iteritems(gauge_metrics):
aggregator.assert_metric(name, value=value, tags=tags)
aggregator.assert_metric(name, value=value, tags=gauge_tags)

for name, value in iteritems(rate_metrics):
aggregator.assert_metric(name, value=value, tags=['device:{}'.format(DEFAULT_DEVICE_NAME)])
aggregator.assert_metric(name, value=value, tags=rate_tags)

aggregator.assert_all_metrics_covered()

Expand Down Expand Up @@ -118,12 +124,18 @@ def test_device_tagging(aggregator, gauge_metrics, rate_metrics):
c.check(instance)

# Assert metrics
tags = ['type:dev', 'tag:two', 'device:{}'.format(DEFAULT_DEVICE_NAME), 'optional:tags1']
gauge_tags = ['type:dev', 'tag:two', 'device:{}'.format(DEFAULT_DEVICE_NAME), 'optional:tags1']
rate_tags = ['device:{}'.format(DEFAULT_DEVICE_NAME), 'optional:tags1']

if c.devices_label.get(DEFAULT_DEVICE_NAME):
gauge_tags.append(c.devices_label.get(DEFAULT_DEVICE_NAME))
rate_tags.append(c.devices_label.get(DEFAULT_DEVICE_NAME))

for name, value in iteritems(gauge_metrics):
aggregator.assert_metric(name, value=value, tags=tags)
aggregator.assert_metric(name, value=value, tags=gauge_tags)

for name, value in iteritems(rate_metrics):
aggregator.assert_metric(name, value=value, tags=['device:{}'.format(DEFAULT_DEVICE_NAME), 'optional:tags1'])
aggregator.assert_metric(name, value=value, tags=rate_tags)

aggregator.assert_all_metrics_covered()

Expand Down Expand Up @@ -198,3 +210,15 @@ def test_no_psutil_centos(aggregator, gauge_metrics):
aggregator.assert_metric(name, tags=['device:{}'.format(device)])

aggregator.assert_all_metrics_covered()


def test_get_devices_label():
c = Disk('disk', None, {}, [{}])

with mock.patch(
"datadog_checks.disk.disk.get_subprocess_output",
return_value=mock_blkid_output(),
__name__='get_subprocess_output',
):
labels = c._get_devices_label()
assert labels.get("/dev/mapper/vagrant--vg-root") == "label:DATA"