diff --git a/windows_service/README.md b/windows_service/README.md index 793d9238c3464..2209cbe0f8b7b 100644 --- a/windows_service/README.md +++ b/windows_service/README.md @@ -97,6 +97,8 @@ Beginning with Agent version 7.73, the check automatically adds a `windows_servi See [metadata.csv][19] for a list of metrics provided by this integration. +**Note:** Metrics are tagged with the same tags as the service check. + ### Events The Windows Service check does not include any events. diff --git a/windows_service/changelog.d/21830.added b/windows_service/changelog.d/21830.added new file mode 100644 index 0000000000000..7f68506255a8f --- /dev/null +++ b/windows_service/changelog.d/21830.added @@ -0,0 +1 @@ +Add state metric to windows services diff --git a/windows_service/datadog_checks/windows_service/windows_service.py b/windows_service/datadog_checks/windows_service/windows_service.py index 6ebaefcaa9c6d..7c82adcd56b07 100644 --- a/windows_service/datadog_checks/windows_service/windows_service.py +++ b/windows_service/datadog_checks/windows_service/windows_service.py @@ -343,6 +343,9 @@ def check(self, instance): self.service_check(self.SERVICE_CHECK_NAME, status, tags=tags) self.log.debug('service state for %s %s', service_name, status) self.gauge('windows_service.uptime', service_uptime, tags=tags) + # Send 1 for windows_service.state so the user can sum by the windows_service_state tag + # to filter services by state. e.g. sum:windows_service.state{*} by windows_service_state + self.gauge('windows_service.state', 1, tags=tags) if 'ALL' not in services: for service in services_unseen: @@ -365,3 +368,5 @@ def check(self, instance): self.service_check(self.SERVICE_CHECK_NAME, status, tags=tags) self.log.debug('service state for %s %s', service, status) + self.gauge('windows_service.uptime', 0, tags=tags) + self.gauge('windows_service.state', 1, tags=tags) diff --git a/windows_service/metadata.csv b/windows_service/metadata.csv index 16ce60ea5b7be..19a49e5e698fe 100644 --- a/windows_service/metadata.csv +++ b/windows_service/metadata.csv @@ -1,2 +1,3 @@ metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name,curated_metric,sample_tags -windows_service.uptime,gauge,,second,,The uptime (in seconds) of the host process of the Windows service,0,windows_service,uptime,, \ No newline at end of file +windows_service.state,gauge,,service,,Sum by state to count the number of services in each state,0,windows_service,state,, +windows_service.uptime,gauge,,second,,The uptime (in seconds) of the host process of the Windows service,0,windows_service,uptime,, diff --git a/windows_service/tests/test_windows_service.py b/windows_service/tests/test_windows_service.py index e94425bbdb9e9..66656f3f64985 100644 --- a/windows_service/tests/test_windows_service.py +++ b/windows_service/tests/test_windows_service.py @@ -5,12 +5,45 @@ import pytest import pywintypes +import win32service import winerror from mock import patch from datadog_checks.windows_service import WindowsService +class ServiceAssertion: + def __init__(self, name, state, extra_tags=None, count=1): + self.name = name + self.check_status = WindowsService.STATE_TO_STATUS.get(state, WindowsService.UNKNOWN) + self.tags = [ + f'windows_service:{name}', + f'windows_service_state:{WindowsService.STATE_TO_STRING.get(state, WindowsService.UNKNOWN_LITERAL)}', + ] + (extra_tags or []) + self.count = count + + +def assert_service_check_and_metrics(aggregator, services): + for service in services: + aggregator.assert_service_check( + WindowsService.SERVICE_CHECK_NAME, + status=service.check_status, + tags=service.tags, + count=service.count, + ) + aggregator.assert_metric( + 'windows_service.uptime', + tags=service.tags, + count=service.count, + ) + aggregator.assert_metric( + 'windows_service.state', + tags=service.tags, + value=1, + count=service.count, + ) + + def test_bad_config(check, instance_bad_config): c = check(instance_bad_config) with pytest.raises(ValueError): @@ -20,127 +53,36 @@ def test_bad_config(check, instance_bad_config): def test_basic(aggregator, check, instance_basic): c = check(instance_basic) c.check(instance_basic) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['service:EventLog', 'windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['service:Dnscache', 'windows_service:Dnscache', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.UNKNOWN, - tags=[ - 'service:NonExistentService', - 'windows_service:NonExistentService', - 'windows_service_state:unknown', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:EventLog', 'windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:Dnscache', 'windows_service:Dnscache', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=[ - 'service:NonExistentService', - 'windows_service:NonExistentService', - 'windows_service_state:unknown', - 'optional:tag1', - ], - count=0, - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING, extra_tags=['service:EventLog', 'optional:tag1']), + ServiceAssertion('Dnscache', win32service.SERVICE_RUNNING, extra_tags=['service:Dnscache', 'optional:tag1']), + ServiceAssertion('NonExistentService', -1, extra_tags=['service:NonExistentService', 'optional:tag1']), + ] + assert_service_check_and_metrics(aggregator, services) def test_wildcard(aggregator, check, instance_wildcard): c = check(instance_wildcard) c.check(instance_wildcard) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['service:EventLog', 'windows_service:EventLog', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['service:EventSystem', 'windows_service:EventSystem', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['service:Dnscache', 'windows_service:Dnscache', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:EventLog', 'windows_service:EventLog', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:EventSystem', 'windows_service:EventSystem', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:Dnscache', 'windows_service:Dnscache', 'windows_service_state:running'], - count=1, - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING, extra_tags=['service:EventLog']), + ServiceAssertion('EventSystem', win32service.SERVICE_RUNNING, extra_tags=['service:EventSystem']), + ServiceAssertion('Dnscache', win32service.SERVICE_RUNNING, extra_tags=['service:Dnscache']), + ] + assert_service_check_and_metrics(aggregator, services) def test_all(aggregator, check, instance_all): c = check(instance_all) c.check(instance_all) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['service:EventLog', 'windows_service:EventLog', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['service:Dnscache', 'windows_service:Dnscache', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['service:EventSystem', 'windows_service:EventSystem', 'windows_service_state:running'], - count=1, - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING, extra_tags=['service:EventLog']), + ServiceAssertion('EventSystem', win32service.SERVICE_RUNNING, extra_tags=['service:EventSystem']), + ServiceAssertion('Dnscache', win32service.SERVICE_RUNNING, extra_tags=['service:Dnscache']), + ] + assert_service_check_and_metrics(aggregator, services) msg = 'The `service` tag is deprecated and has been renamed to `windows_service`' assert msg in c.warnings[0] - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:EventLog', 'windows_service:EventLog', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:Dnscache', 'windows_service:Dnscache', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:EventSystem', 'windows_service:EventSystem', 'windows_service_state:running'], - count=1, - ) def test_startup_type_filter_automatic(aggregator, check, instance_startup_type_filter): @@ -183,70 +125,24 @@ def test_name_dict_basic(aggregator, check, instance_basic_dict): c = check(instance_basic_dict) c.check(instance_basic_dict) - # Check count - aggregator.assert_service_check(c.SERVICE_CHECK_NAME, status=c.OK, count=2) - aggregator.assert_service_check(c.SERVICE_CHECK_NAME, status=c.UNKNOWN, count=1) - # Check details - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['windows_service:Dnscache', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.UNKNOWN, - tags=['windows_service:NonExistentService', 'windows_service_state:unknown', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['windows_service:Dnscache', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['windows_service:NonExistentService', 'windows_service_state:unknown', 'optional:tag1'], - count=0, - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING, extra_tags=['optional:tag1']), + ServiceAssertion('Dnscache', win32service.SERVICE_RUNNING, extra_tags=['optional:tag1']), + ServiceAssertion('NonExistentService', -1, extra_tags=['optional:tag1']), + ] + assert_service_check_and_metrics(aggregator, services) def test_name_dict_wildcard_with_wmi_compat(aggregator, check, instance_wildcard_dict): c = check(instance_wildcard_dict) c.check(instance_wildcard_dict) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, status=c.OK, tags=['windows_service:EventLog', 'windows_service_state:running'], count=1 - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['windows_service:EventSystem', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, status=c.OK, tags=['windows_service:Dnscache', 'windows_service_state:running'], count=1 - ) - aggregator.assert_metric( - 'windows_service.uptime', tags=['windows_service:EventLog', 'windows_service_state:running'], count=1 - ) - aggregator.assert_metric( - 'windows_service.uptime', tags=['windows_service:EventSystem', 'windows_service_state:running'], count=1 - ) - aggregator.assert_metric( - 'windows_service.uptime', tags=['windows_service:Dnscache', 'windows_service_state:running'], count=1 - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING), + ServiceAssertion('EventSystem', win32service.SERVICE_RUNNING), + ServiceAssertion('Dnscache', win32service.SERVICE_RUNNING), + ] + assert_service_check_and_metrics(aggregator, services) def test_startup_type_filter_name_dict_wildcard_without_wmi_compat(aggregator, check, instance_wildcard_dict): @@ -255,24 +151,12 @@ def test_startup_type_filter_name_dict_wildcard_without_wmi_compat(aggregator, c c = check(instance_wildcard_dict) c.check(instance_wildcard_dict) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, status=c.OK, tags=['windows_service:EventLog', 'windows_service_state:running'], count=1 - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['windows_service:EventSystem', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, status=c.OK, tags=['windows_service:Dnscache', 'windows_service_state:running'], count=0 - ) - aggregator.assert_metric( - 'windows_service.uptime', tags=['windows_service:EventLog', 'windows_service_state:running'], count=1 - ) - aggregator.assert_metric( - 'windows_service.uptime', tags=['windows_service:EventSystem', 'windows_service_state:running'], count=1 - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING), + ServiceAssertion('EventSystem', win32service.SERVICE_RUNNING), + ServiceAssertion('Dnscache', -1, count=0), + ] + assert_service_check_and_metrics(aggregator, services) def test_startup_type_filter_automatic_single_without_tag(aggregator, check, instance_startup_type_filter): @@ -287,202 +171,75 @@ def test_startup_type_filter_automatic_single_without_tag(aggregator, check, ins c = check(instance_startup_type_filter) c.check(instance_startup_type_filter) - # Make sure we got exactly one - aggregator.assert_service_check(c.SERVICE_CHECK_NAME, status=c.OK, count=1) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, status=c.OK, tags=['windows_service:EventLog', 'windows_service_state:running'], count=1 - ) - aggregator.assert_metric( - 'windows_service.uptime', tags=['windows_service:EventLog', 'windows_service_state:running'], count=1 - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING), + ] + assert_service_check_and_metrics(aggregator, services) def test_basic_disable_service_tag(aggregator, check, instance_basic_disable_service_tag): c = check(instance_basic_disable_service_tag) c.check(instance_basic_disable_service_tag) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=['windows_service:Dnscache', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.UNKNOWN, - tags=['windows_service:NonExistentService', 'windows_service_state:unknown', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['windows_service:Dnscache', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['windows_service:NonExistentService', 'windows_service_state:unknown', 'optional:tag1'], - count=0, - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING, extra_tags=['optional:tag1']), + ServiceAssertion('Dnscache', win32service.SERVICE_RUNNING, extra_tags=['optional:tag1']), + ServiceAssertion('NonExistentService', -1, extra_tags=['optional:tag1']), + ] + assert_service_check_and_metrics(aggregator, services) def test_startup_type_tag(aggregator, check, instance_basic): instance_basic['windows_service_startup_type_tag'] = True c = check(instance_basic) c.check(instance_basic) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=[ - 'service:EventLog', - 'windows_service:EventLog', - 'windows_service_state:running', - 'windows_service_startup_type:automatic', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=[ - 'service:Dnscache', - 'windows_service:Dnscache', - 'windows_service_state:running', - 'windows_service_startup_type:automatic', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.UNKNOWN, - tags=[ - 'service:NonExistentService', - 'windows_service:NonExistentService', - 'windows_service_state:unknown', - 'windows_service_startup_type:unknown', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=[ - 'service:EventLog', - 'windows_service:EventLog', - 'windows_service_state:running', - 'windows_service_startup_type:automatic', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=[ - 'service:Dnscache', - 'windows_service:Dnscache', - 'windows_service_state:running', - 'windows_service_startup_type:automatic', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=[ - 'service:NonExistentService', - 'windows_service:NonExistentService', - 'windows_service_state:unknown', - 'windows_service_startup_type:unknown', - 'optional:tag1', - ], - count=0, - ) + services = [ + ServiceAssertion( + 'EventLog', + win32service.SERVICE_RUNNING, + extra_tags=['service:EventLog', 'windows_service_startup_type:automatic', 'optional:tag1'], + count=1, + ), + ServiceAssertion( + 'Dnscache', + win32service.SERVICE_RUNNING, + extra_tags=['service:Dnscache', 'windows_service_startup_type:automatic', 'optional:tag1'], + count=1, + ), + ServiceAssertion( + 'NonExistentService', + -1, + extra_tags=['service:NonExistentService', 'windows_service_startup_type:unknown', 'optional:tag1'], + count=1, + ), + ] + assert_service_check_and_metrics(aggregator, services) def test_display_name_tag(aggregator, check, instance_basic): instance_basic['collect_display_name_as_tag'] = True c = check(instance_basic) c.check(instance_basic) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=[ - 'service:EventLog', - 'windows_service:EventLog', - 'windows_service_state:running', - 'display_name:Windows Event Log', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.OK, - tags=[ - 'service:Dnscache', - 'windows_service:Dnscache', - 'windows_service_state:running', - 'display_name:DNS Client', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_service_check( - c.SERVICE_CHECK_NAME, - status=c.UNKNOWN, - tags=[ - 'service:NonExistentService', - 'windows_service:NonExistentService', - 'windows_service_state:unknown', - 'display_name:Not_Found', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=[ - 'service:EventLog', - 'windows_service:EventLog', - 'windows_service_state:running', - 'display_name:Windows Event Log', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=[ - 'service:Dnscache', - 'windows_service:Dnscache', - 'windows_service_state:running', - 'display_name:DNS Client', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=[ - 'service:NonExistentService', - 'windows_service:NonExistentService', - 'windows_service_state:unknown', - 'display_name:Not_Found', - 'optional:tag1', - ], - count=0, - ) + services = [ + ServiceAssertion( + 'EventLog', + win32service.SERVICE_RUNNING, + extra_tags=['service:EventLog', 'display_name:Windows Event Log', 'optional:tag1'], + count=1, + ), + ServiceAssertion( + 'Dnscache', + win32service.SERVICE_RUNNING, + extra_tags=['service:Dnscache', 'display_name:DNS Client', 'optional:tag1'], + count=1, + ), + ServiceAssertion( + 'NonExistentService', + -1, + extra_tags=['service:NonExistentService', 'display_name:Not_Found', 'optional:tag1'], + count=1, + ), + ] + assert_service_check_and_metrics(aggregator, services) def test_openservice_failure(aggregator, check, instance_basic_dict, caplog): @@ -523,25 +280,11 @@ def test_invalid_pattern_regex(aggregator, check, instance_basic_dict): def test_trigger_start(aggregator, check, instance_trigger_start): c = check(instance_trigger_start) c.check(instance_trigger_start) - aggregator.assert_service_check( - WindowsService.SERVICE_CHECK_NAME, - status=WindowsService.OK, - tags=['windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - - aggregator.assert_service_check( - WindowsService.SERVICE_CHECK_NAME, - status=WindowsService.UNKNOWN, - tags=['windows_service:dnscache', 'windows_service_state:unknown', 'optional:tag1'], - count=1, - ) - - aggregator.assert_metric( - 'windows_service.uptime', - tags=['windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING, extra_tags=['optional:tag1']), + ServiceAssertion('dnscache', -1, extra_tags=['optional:tag1']), + ] + assert_service_check_and_metrics(aggregator, services) def test_trigger_count_failure(aggregator, check, instance_trigger_start, caplog): @@ -572,78 +315,23 @@ def test_name_regex_order(aggregator, check, instance_name_regex_prefix): c = check(instance_name_regex_prefix) c.check(instance_name_regex_prefix) - # More specific names should match - aggregator.assert_service_check( - WindowsService.SERVICE_CHECK_NAME, - status=WindowsService.OK, - tags=['windows_service:EventLog', 'windows_service_state:running'], - count=1, - ) - aggregator.assert_service_check( - WindowsService.SERVICE_CHECK_NAME, - status=WindowsService.OK, - tags=['windows_service:EventSystem', 'windows_service_state:running'], - count=1, - ) - # The prefix match should go unmatched, even though it is listed first in the config - aggregator.assert_service_check( - WindowsService.SERVICE_CHECK_NAME, - status=WindowsService.UNKNOWN, - tags=['windows_service:event', 'windows_service_state:unknown'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', tags=['windows_service:EventLog', 'windows_service_state:running'], count=1 - ) - aggregator.assert_metric( - 'windows_service.uptime', tags=['windows_service:EventSystem', 'windows_service_state:running'], count=1 - ) + services = [ + # More specific names should match + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING), + ServiceAssertion('EventSystem', win32service.SERVICE_RUNNING), + # The prefix match should go unmatched, even though it is listed first in the config + ServiceAssertion('event', -1, count=1), + ] + assert_service_check_and_metrics(aggregator, services) @pytest.mark.e2e def test_basic_e2e(dd_agent_check, check, instance_basic): aggregator = dd_agent_check(instance_basic) - aggregator.assert_service_check( - WindowsService.SERVICE_CHECK_NAME, - status=WindowsService.OK, - tags=['service:EventLog', 'windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_service_check( - WindowsService.SERVICE_CHECK_NAME, - status=WindowsService.OK, - tags=['service:Dnscache', 'windows_service:Dnscache', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_service_check( - WindowsService.SERVICE_CHECK_NAME, - status=WindowsService.UNKNOWN, - tags=[ - 'service:NonExistentService', - 'windows_service:NonExistentService', - 'windows_service_state:unknown', - 'optional:tag1', - ], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:EventLog', 'windows_service:EventLog', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=['service:Dnscache', 'windows_service:Dnscache', 'windows_service_state:running', 'optional:tag1'], - count=1, - ) - aggregator.assert_metric( - 'windows_service.uptime', - tags=[ - 'service:NonExistentService', - 'windows_service:NonExistentService', - 'windows_service_state:unknown', - 'optional:tag1', - ], - count=0, - ) + services = [ + ServiceAssertion('EventLog', win32service.SERVICE_RUNNING, extra_tags=['service:EventLog', 'optional:tag1']), + ServiceAssertion('Dnscache', win32service.SERVICE_RUNNING, extra_tags=['service:Dnscache', 'optional:tag1']), + ServiceAssertion('NonExistentService', -1, extra_tags=['service:NonExistentService', 'optional:tag1']), + ] + assert_service_check_and_metrics(aggregator, services)