diff --git a/windows_service/assets/configuration/spec.yaml b/windows_service/assets/configuration/spec.yaml index 9375d37802197..8ca09ba7c7997 100644 --- a/windows_service/assets/configuration/spec.yaml +++ b/windows_service/assets/configuration/spec.yaml @@ -64,4 +64,16 @@ files: value: type: boolean example: false + - name: collect_display_name_as_tag + description: | + Whether or not to submit the Windows Service Display Name as the `display_name` tag. + `display_name` will be formatted according to Datadog's tagging requirements: + https://docs.datadoghq.com/getting_started/tagging/#define-tags + + Example of the default `windows_service` tag and `display_name` tag: + windows_service:wuauserv + display_name:windows_update + value: + type: boolean + example: false - template: instances/default diff --git a/windows_service/changelog.d/17657.added b/windows_service/changelog.d/17657.added new file mode 100644 index 0000000000000..204f0575ceb25 --- /dev/null +++ b/windows_service/changelog.d/17657.added @@ -0,0 +1 @@ +Add optional display_name tag \ No newline at end of file diff --git a/windows_service/datadog_checks/windows_service/config_models/defaults.py b/windows_service/datadog_checks/windows_service/config_models/defaults.py index 6dc77155d16f7..15e17f5c83887 100644 --- a/windows_service/datadog_checks/windows_service/config_models/defaults.py +++ b/windows_service/datadog_checks/windows_service/config_models/defaults.py @@ -8,6 +8,10 @@ # ddev -x validate models -s +def instance_collect_display_name_as_tag(): + return False + + def instance_disable_generic_tags(): return False diff --git a/windows_service/datadog_checks/windows_service/config_models/instance.py b/windows_service/datadog_checks/windows_service/config_models/instance.py index 55de174948edf..d62e835362aa3 100644 --- a/windows_service/datadog_checks/windows_service/config_models/instance.py +++ b/windows_service/datadog_checks/windows_service/config_models/instance.py @@ -35,6 +35,7 @@ class InstanceConfig(BaseModel): arbitrary_types_allowed=True, frozen=True, ) + collect_display_name_as_tag: Optional[bool] = None disable_generic_tags: Optional[bool] = None disable_legacy_service_tag: Optional[bool] = None empty_default_hostname: Optional[bool] = None diff --git a/windows_service/datadog_checks/windows_service/data/conf.yaml.example b/windows_service/datadog_checks/windows_service/data/conf.yaml.example index 3b4a22c6753e5..ad1cb5354788f 100644 --- a/windows_service/datadog_checks/windows_service/data/conf.yaml.example +++ b/windows_service/datadog_checks/windows_service/data/conf.yaml.example @@ -61,6 +61,17 @@ instances: # # windows_service_startup_type_tag: false + ## @param collect_display_name_as_tag - boolean - optional - default: false + ## Whether or not to submit the Windows Service Display Name as the `display_name` tag. + ## `display_name` will be formatted according to Datadog's tagging requirements: + ## https://docs.datadoghq.com/getting_started/tagging/#define-tags + ## + ## Example of the default `windows_service` tag and `display_name` tag: + ## windows_service:wuauserv + ## display_name:windows_update + # + # collect_display_name_as_tag: false + ## @param tags - list of strings - optional ## A list of tags to attach to every metric and service check emitted by this instance. ## diff --git a/windows_service/datadog_checks/windows_service/windows_service.py b/windows_service/datadog_checks/windows_service/windows_service.py index 28eee99b14154..fb2c10860ab52 100644 --- a/windows_service/datadog_checks/windows_service/windows_service.py +++ b/windows_service/datadog_checks/windows_service/windows_service.py @@ -259,7 +259,7 @@ def check(self, instance): # See test_name_regex_order() service_filters = sorted(service_filters, reverse=True, key=lambda x: len(x.name or "")) - for short_name, _, service_status in service_statuses: + for short_name, display_name, service_status in service_statuses: service_view = ServiceView(scm_handle, short_name) if 'ALL' not in services: @@ -285,6 +285,9 @@ def check(self, instance): tags = ['windows_service:{}'.format(short_name)] tags.extend(custom_tags) + if instance.get('collect_display_name_as_tag', False): + tags.append('display_name:{}'.format(display_name)) + if instance.get('windows_service_startup_type_tag', False): try: tags.append('windows_service_startup_type:{}'.format(service_view.startup_type_string())) @@ -306,6 +309,7 @@ def check(self, instance): # if a name doesn't match anything (wrong name or no permission to access the service), report UNKNOWN status = self.UNKNOWN startup_type_string = ServiceView.STARTUP_TYPE_UNKNOWN + display_name = "Not_Found" tags = ['windows_service:{}'.format(service)] @@ -314,6 +318,9 @@ def check(self, instance): if instance.get('windows_service_startup_type_tag', False): tags.append('windows_service_startup_type:{}'.format(startup_type_string)) + if instance.get('collect_display_name_as_tag', False): + tags.append('display_name:{}'.format(display_name)) + if not instance.get('disable_legacy_service_tag', False): self._log_deprecation('service_tag', 'windows_service') tags.append('service:{}'.format(service)) diff --git a/windows_service/tests/test_windows_service.py b/windows_service/tests/test_windows_service.py index 5407f5bb3f03a..95cdb819ff1a2 100644 --- a/windows_service/tests/test_windows_service.py +++ b/windows_service/tests/test_windows_service.py @@ -221,6 +221,45 @@ def test_startup_type_tag(aggregator, check, instance_basic): ) +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', + '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', + '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', + 'display_name:Not_Found', + 'optional:tag1', + ], + count=1, + ) + + def test_openservice_failure(aggregator, check, instance_basic_dict, caplog): # dict type instance_basic_dict['services'].append({'startup_type': 'automatic'})