From cddcce282b66a5202eb9debcc0ed809043aa279d Mon Sep 17 00:00:00 2001 From: Ofek Lev Date: Tue, 2 Nov 2021 23:52:42 -0400 Subject: [PATCH 1/2] Support new implementation of Windows performance counters on Python 3 --- iis/datadog_checks/iis/check.py | 120 ++++++++++++++++++++++++++++++ iis/datadog_checks/iis/iis.py | 10 ++- iis/datadog_checks/iis/metrics.py | 49 ++++++++++++ iis/tests/common.py | 8 ++ iis/tests/conftest.py | 10 --- iis/tests/test_iis.py | 16 ++-- iis/tests/test_unit.py | 114 ++++++++++++++++++++++++++++ 7 files changed, 309 insertions(+), 18 deletions(-) create mode 100644 iis/datadog_checks/iis/check.py create mode 100644 iis/datadog_checks/iis/metrics.py delete mode 100644 iis/tests/conftest.py create mode 100644 iis/tests/test_unit.py diff --git a/iis/datadog_checks/iis/check.py b/iis/datadog_checks/iis/check.py new file mode 100644 index 0000000000000..b477e9162ab4c --- /dev/null +++ b/iis/datadog_checks/iis/check.py @@ -0,0 +1,120 @@ +# (C) Datadog, Inc. 2021-present +# All rights reserved +# Licensed under a 3-clause BSD style license (see LICENSE) +from datadog_checks.base.checks.windows.perf_counters.base import PerfCountersBaseCheckWithLegacySupport +from datadog_checks.base.checks.windows.perf_counters.counter import PerfObject +from datadog_checks.base.constants import ServiceCheck + +from .metrics import METRICS_CONFIG + + +class IISCheckV2(PerfCountersBaseCheckWithLegacySupport): + __NAMESPACE__ = 'iis' + + def get_default_config(self): + metrics_config = {} + for object_name, config in METRICS_CONFIG.items(): + new_config = config.copy() + + include = [] + if object_name == 'APP_POOL_WAS': + new_config['tag_name'] = 'app_pool' + include.extend(self.instance.get('app_pools', [])) + elif object_name == 'Web Service': + new_config['tag_name'] = 'site' + include.extend(self.instance.get('sites', [])) + + if include: + new_config['include'] = [f'^{instance}$' for instance in include] + + metrics_config[object_name] = new_config + + return {'server_tag': 'iis_host', 'metrics': metrics_config} + + def get_perf_object(self, connection, object_name, object_config, use_localized_counters, tags): + if object_name == 'APP_POOL_WAS': + return CompatibilityPerfObject( + self, + connection, + object_name, + object_config, + use_localized_counters, + tags, + 'Current Application Pool Uptime', + 'app_pool', + self.instance.get('app_pools', []), + ) + elif object_name == 'Web Service': + return CompatibilityPerfObject( + self, + connection, + object_name, + object_config, + use_localized_counters, + tags, + 'Service Uptime', + 'site', + self.instance.get('sites', []), + ) + else: + return super().get_perf_object(connection, object_name, object_config, use_localized_counters, tags) + + +class CompatibilityPerfObject(PerfObject): + def __init__( + self, + check, + connection, + object_name, + object_config, + use_localized_counters, + tags, + uptime_counter, + instance_type, + instances_included, + ): + super().__init__(check, connection, object_name, object_config, use_localized_counters, tags) + + self.uptime_counter = uptime_counter + self.instance_type = instance_type + self.instance_service_check_name = f'{self.instance_type}_up' + self.instances_included = set(instances_included) + + # Resets during refreshes + self.instances_unseen = set() + + def refresh(self): + self.instances_unseen.clear() + self.instances_unseen.update(self.instances_included) + + for instance in sorted(self.instances_unseen): + self.logger.debug('Expecting %ss: %s', self.instance_type, instance) + + super().refresh() + + for instance in sorted(self.instances_unseen): + tags = [f'{self.instance_type}:{instance}'] + tags.extend(self.tags) + self.logger.warning('Did not get any data for expected %s: %s', self.instance_type, instance) + self.check.service_check(self.instance_service_check_name, ServiceCheck.CRITICAL, tags=tags) + + def _instance_excluded(self, instance): + self.instances_unseen.discard(instance) + return super()._instance_excluded(instance) + + def get_custom_transformers(self): + return {self.uptime_counter: self.__get_uptime_transformer} + + def __get_uptime_transformer(self, check, metric_name, modifiers): + gauge_method = check.gauge + service_check_method = check.service_check + + def submit_uptime(value, tags=None): + gauge_method(metric_name, value, tags=tags) + service_check_method( + self.instance_service_check_name, ServiceCheck.CRITICAL if value == 0 else ServiceCheck.OK, tags=tags + ) + + del check + del modifiers + return submit_uptime diff --git a/iis/datadog_checks/iis/iis.py b/iis/datadog_checks/iis/iis.py index 6462b0f650487..c6c2b0d7daab2 100644 --- a/iis/datadog_checks/iis/iis.py +++ b/iis/datadog_checks/iis/iis.py @@ -1,7 +1,7 @@ # (C) Datadog, Inc. 2010-present # All rights reserved # Licensed under Simplified BSD License (see LICENSE) -from six import iteritems +from six import PY3, iteritems from datadog_checks.base import PDHBaseCheck @@ -46,6 +46,14 @@ class IIS(PDHBaseCheck): SITE = 'site' APP_POOL = 'app_pool' + def __new__(cls, name, init_config, instances): + if PY3: + from .check import IISCheckV2 + + return IISCheckV2(name, init_config, instances) + else: + return super(IIS, cls).__new__(cls) + def __init__(self, name, init_config, instances): super(IIS, self).__init__(name, init_config, instances, counter_list=DEFAULT_COUNTERS) self._sites = self.instance.get('sites', []) diff --git a/iis/datadog_checks/iis/metrics.py b/iis/datadog_checks/iis/metrics.py new file mode 100644 index 0000000000000..e8b167b22bb54 --- /dev/null +++ b/iis/datadog_checks/iis/metrics.py @@ -0,0 +1,49 @@ +# (C) Datadog, Inc. 2021-present +# All rights reserved +# Licensed under a 3-clause BSD style license (see LICENSE) +METRICS_CONFIG = { + 'APP_POOL_WAS': { + 'name': 'app_pool', + 'counters': [ + { + 'Current Application Pool State': 'state', + 'Current Application Pool Uptime': 'uptime', + 'Total Application Pool Recycles': {'name': 'recycle.count', 'type': 'monotonic_count'}, + } + ], + }, + 'Web Service': { + 'name': 'web_service', + 'counters': [ + { + 'Service Uptime': {'metric_name': 'uptime'}, + # Network + 'Bytes Sent/sec': {'metric_name': 'net.bytes_sent'}, + 'Bytes Received/sec': {'metric_name': 'net.bytes_rcvd'}, + 'Bytes Total/sec': {'metric_name': 'net.bytes_total'}, + 'Current Connections': {'metric_name': 'net.num_connections'}, + 'Files Sent/sec': {'metric_name': 'net.files_sent'}, + 'Files Received/sec': {'metric_name': 'net.files_rcvd'}, + 'Total Connection Attempts (all instances)': {'metric_name': 'net.connection_attempts'}, + 'Connection Attempts/sec': {'metric_name': 'net.connection_attempts_sec'}, + # HTTP methods + 'Get Requests/sec': {'metric_name': 'httpd_request_method.get'}, + 'Post Requests/sec': {'metric_name': 'httpd_request_method.post'}, + 'Head Requests/sec': {'metric_name': 'httpd_request_method.head'}, + 'Put Requests/sec': {'metric_name': 'httpd_request_method.put'}, + 'Delete Requests/sec': {'metric_name': 'httpd_request_method.delete'}, + 'Options Requests/sec': {'metric_name': 'httpd_request_method.options'}, + 'Trace Requests/sec': {'metric_name': 'httpd_request_method.trace'}, + # Errors + 'Not Found Errors/sec': {'metric_name': 'errors.not_found'}, + 'Locked Errors/sec': {'metric_name': 'errors.locked'}, + # Users + 'Anonymous Users/sec': {'metric_name': 'users.anon'}, + 'NonAnonymous Users/sec': {'metric_name': 'users.nonanon'}, + # Requests + 'CGI Requests/sec': {'metric_name': 'requests.cgi'}, + 'ISAPI Extension Requests/sec': {'metric_name': 'requests.isapi'}, + } + ], + }, +} diff --git a/iis/tests/common.py b/iis/tests/common.py index aa656b5ef1045..bbc5e6648301a 100644 --- a/iis/tests/common.py +++ b/iis/tests/common.py @@ -2,6 +2,7 @@ # All rights reserved # Licensed under Simplified BSD License (see LICENSE) from datadog_checks.iis.iis import DEFAULT_COUNTERS +from datadog_checks.iis.metrics import METRICS_CONFIG CHECK_NAME = 'iis' MINIMAL_INSTANCE = {'host': '.'} @@ -43,3 +44,10 @@ SITE_METRICS = [counter_data[3] for counter_data in DEFAULT_COUNTERS if counter_data[0] == 'Web Service'] APP_POOL_METRICS = [counter_data[3] for counter_data in DEFAULT_COUNTERS if counter_data[0] == 'APP_POOL_WAS'] + +PERFORMANCE_OBJECTS = {} +for object_name, instances in (('APP_POOL_WAS', ['foo-pool', 'bar-pool']), ('Web Service', ['foo.site', 'bar.site'])): + PERFORMANCE_OBJECTS[object_name] = ( + instances, + {counter: [9000, 0] for counter in METRICS_CONFIG[object_name]['counters'][0]}, + ) diff --git a/iis/tests/conftest.py b/iis/tests/conftest.py deleted file mode 100644 index dfa264379d2d3..0000000000000 --- a/iis/tests/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -# (C) Datadog, Inc. 2010-present -# All rights reserved -# Licensed under Simplified BSD License (see LICENSE) -import pytest -from datadog_test_libs.win.pdh_mocks import initialize_pdh_tests - - -@pytest.fixture(scope="function", autouse=True) -def setup_check(): - initialize_pdh_tests() diff --git a/iis/tests/test_iis.py b/iis/tests/test_iis.py index f01f0d07b3403..42f7973a22ae1 100644 --- a/iis/tests/test_iis.py +++ b/iis/tests/test_iis.py @@ -6,8 +6,9 @@ import re import pytest -from datadog_test_libs.win.pdh_mocks import pdh_mocks_fixture # noqa: F401 +from datadog_test_libs.win.pdh_mocks import initialize_pdh_tests, pdh_mocks_fixture # noqa: F401 +from datadog_checks.dev.testing import requires_py2 from datadog_checks.iis import IIS from .common import ( @@ -23,8 +24,14 @@ WIN_SERVICES_MINIMAL_CONFIG, ) +pytestmark = [requires_py2, pytest.mark.usefixtures('pdh_mocks_fixture')] + + +@pytest.fixture(autouse=True) +def setup_check(): + initialize_pdh_tests() + -@pytest.mark.usefixtures('pdh_mocks_fixture') def test_additional_metrics(aggregator, caplog, dd_run_check): instance = copy.deepcopy(MINIMAL_INSTANCE) instance['additional_metrics'] = [ @@ -46,7 +53,6 @@ def test_additional_metrics(aggregator, caplog, dd_run_check): assert 'Unknown IIS counter: HTTP Service Request Queues. Falling back to default submission' in caplog.text -@pytest.mark.usefixtures('pdh_mocks_fixture') def test_basic_check(aggregator, dd_run_check): instance = MINIMAL_INSTANCE c = IIS(CHECK_NAME, {}, [instance]) @@ -68,7 +74,6 @@ def test_basic_check(aggregator, dd_run_check): aggregator.assert_all_metrics_covered() -@pytest.mark.usefixtures('pdh_mocks_fixture') def test_check_on_specific_websites_and_app_pools(aggregator, dd_run_check): instance = INSTANCE c = IIS(CHECK_NAME, {}, [instance]) @@ -98,7 +103,6 @@ def test_check_on_specific_websites_and_app_pools(aggregator, dd_run_check): aggregator.assert_all_metrics_covered() -@pytest.mark.usefixtures('pdh_mocks_fixture') def test_service_check_with_invalid_host(aggregator, dd_run_check): instance = INVALID_HOST_INSTANCE c = IIS(CHECK_NAME, {}, [instance]) @@ -109,7 +113,6 @@ def test_service_check_with_invalid_host(aggregator, dd_run_check): aggregator.assert_service_check('iis.app_pool_up', IIS.CRITICAL, tags=['app_pool:Total', iis_host]) -@pytest.mark.usefixtures('pdh_mocks_fixture') def test_check(aggregator, dd_run_check): """ Returns the right metrics and service checks @@ -160,7 +163,6 @@ def test_check(aggregator, dd_run_check): aggregator.assert_all_metrics_covered() -@pytest.mark.usefixtures('pdh_mocks_fixture') def test_check_without_sites_specified(aggregator, dd_run_check): """ Returns the right metrics and service checks for the `_Total` site diff --git a/iis/tests/test_unit.py b/iis/tests/test_unit.py new file mode 100644 index 0000000000000..5fd40537353d7 --- /dev/null +++ b/iis/tests/test_unit.py @@ -0,0 +1,114 @@ +# (C) Datadog, Inc. 2021-present +# All rights reserved +# Licensed under a 3-clause BSD style license (see LICENSE) +from datadog_checks.base.constants import ServiceCheck +from datadog_checks.dev.testing import requires_py3 +from datadog_checks.iis import IIS + +from .common import DEFAULT_COUNTERS, PERFORMANCE_OBJECTS + +pytestmark = [requires_py3] + + +def get_metrics_data(): + app_pool_metrics_data = [] + site_metrics_data = [] + + for counter_data in DEFAULT_COUNTERS: + object_name = counter_data[0] + if object_name == 'APP_POOL_WAS': + app_pool_metrics_data.append((counter_data[3], counter_data[4])) + elif object_name == 'Web Service': + site_metrics_data.append((counter_data[3], counter_data[4])) + + return app_pool_metrics_data, site_metrics_data + + +def test_check_all(aggregator, dd_default_hostname, dd_run_check, mock_performance_objects): + mock_performance_objects(PERFORMANCE_OBJECTS) + check = IIS('iis', {}, [{'host': dd_default_hostname}]) + check.hostname = dd_default_hostname + dd_run_check(check) + + global_tags = ['iis_host:{}'.format(dd_default_hostname)] + aggregator.assert_service_check('iis.windows.perf.health', ServiceCheck.OK, count=1, tags=global_tags) + + app_pool_metrics_data, site_metrics_data = get_metrics_data() + + for app_pool, value in (('foo-pool', 9000), ('bar-pool', 0)): + tags = ['app_pool:{}'.format(app_pool)] + tags.extend(global_tags) + aggregator.assert_service_check( + 'iis.app_pool_up', ServiceCheck.CRITICAL if value == 0 else ServiceCheck.OK, count=1, tags=tags + ) + + for metric_name, metric_type in app_pool_metrics_data: + aggregator.assert_metric( + metric_name, value, metric_type=getattr(aggregator, metric_type.upper()), count=1, tags=tags + ) + + for site, value in (('foo.site', 9000), ('bar.site', 0)): + tags = ['site:{}'.format(site)] + tags.extend(global_tags) + aggregator.assert_service_check( + 'iis.site_up', ServiceCheck.CRITICAL if value == 0 else ServiceCheck.OK, count=1, tags=tags + ) + + for metric_name, metric_type in site_metrics_data: + aggregator.assert_metric( + metric_name, value, metric_type=getattr(aggregator, metric_type.upper()), count=1, tags=tags + ) + + aggregator.assert_all_metrics_covered() + + +def test_check_specific(aggregator, dd_default_hostname, dd_run_check, mock_performance_objects): + mock_performance_objects(PERFORMANCE_OBJECTS) + check = IIS( + 'iis', + {}, + [ + { + 'host': dd_default_hostname, + 'app_pools': ['foo-pool', 'missing-pool'], + 'sites': ['foo.site', 'missing.site'], + } + ], + ) + check.hostname = dd_default_hostname + dd_run_check(check) + + global_tags = ['iis_host:{}'.format(dd_default_hostname)] + aggregator.assert_service_check('iis.windows.perf.health', ServiceCheck.OK, count=1, tags=global_tags) + + app_pool_metrics_data, site_metrics_data = get_metrics_data() + + for app_pool, value in (('foo-pool', 9000), ('missing-pool', 0)): + tags = ['app_pool:{}'.format(app_pool)] + tags.extend(global_tags) + aggregator.assert_service_check( + 'iis.app_pool_up', ServiceCheck.CRITICAL if value == 0 else ServiceCheck.OK, count=1, tags=tags + ) + + for metric_name, metric_type in app_pool_metrics_data: + aggregator.assert_metric_has_tag(metric_name, 'app_pool:bar-pool', count=0) + if not app_pool.startswith('missing'): + aggregator.assert_metric( + metric_name, value, metric_type=getattr(aggregator, metric_type.upper()), count=1, tags=tags + ) + + for site, value in (('foo.site', 9000), ('missing.site', 0)): + tags = ['site:{}'.format(site)] + tags.extend(global_tags) + aggregator.assert_service_check( + 'iis.site_up', ServiceCheck.CRITICAL if value == 0 else ServiceCheck.OK, count=1, tags=tags + ) + + for metric_name, metric_type in site_metrics_data: + aggregator.assert_metric_has_tag(metric_name, 'site:bar.site', count=0) + if not site.startswith('missing'): + aggregator.assert_metric( + metric_name, value, metric_type=getattr(aggregator, metric_type.upper()), count=1, tags=tags + ) + + aggregator.assert_all_metrics_covered() From db5152c9ced79c0f632df2e8689df589b5c09e53 Mon Sep 17 00:00:00 2001 From: Ofek Lev Date: Tue, 30 Nov 2021 17:40:21 -0500 Subject: [PATCH 2/2] address --- iis/assets/configuration/spec.yaml | 26 +--- .../iis/config_models/defaults.py | 32 +++- .../iis/config_models/instance.py | 82 +++++++++- .../iis/config_models/shared.py | 1 + iis/datadog_checks/iis/data/conf.yaml.example | 146 ++++++++++++------ 5 files changed, 200 insertions(+), 87 deletions(-) diff --git a/iis/assets/configuration/spec.yaml b/iis/assets/configuration/spec.yaml index 276c2f4becef4..d0fcab4cab18b 100644 --- a/iis/assets/configuration/spec.yaml +++ b/iis/assets/configuration/spec.yaml @@ -4,6 +4,7 @@ files: options: - template: init_config options: + - template: init_config/perf_counters - template: init_config/default - template: instances options: @@ -39,30 +40,7 @@ files: compact_example: false items: type: string - - name: is_2008 - required: false - display_priority: 1 - description: | - Because of a typo in IIS6/7 (typically on W2K8) where perfmon reports TotalBytesTransferred as - TotalBytesTransfered, you may have to enable this to grab the IIS metrics in that environment. - value: - example: false - type: boolean - - template: instances/pdh_legacy - overrides: - host.required: true - host.display_priority: 2 - username.display_priority: 2 - password.display_priority: 2 - host.description: | - By default, this check runs against a single instance - the current - machine that the Agent is running on. It checks the PDH (Performance - Data Helper) performance counters for IIS on that machine. - - "." means the current host, any other value makes the Agent attempt to connect to a remote host. - Note: Remote access requires additional permissions. - additional_metrics.value.example: - - ['Web Service', none, 'CGI Requests/sec', iis.httpd_request_method.cgi, gauge] + - template: instances/perf_counters - template: instances/default - template: logs example: diff --git a/iis/datadog_checks/iis/config_models/defaults.py b/iis/datadog_checks/iis/config_models/defaults.py index 3e72fa743238d..f3046c7d269ff 100644 --- a/iis/datadog_checks/iis/config_models/defaults.py +++ b/iis/datadog_checks/iis/config_models/defaults.py @@ -8,18 +8,14 @@ def shared_service(field, value): return get_default_field_value(field, value) -def instance_additional_metrics(field, value): - return get_default_field_value(field, value) +def shared_use_localized_counters(field, value): + return False def instance_app_pools(field, value): return get_default_field_value(field, value) -def instance_counter_data_types(field, value): - return get_default_field_value(field, value) - - def instance_disable_generic_tags(field, value): return False @@ -28,18 +24,38 @@ def instance_empty_default_hostname(field, value): return False -def instance_is_2008(field, value): - return False +def instance_enable_health_service_check(field, value): + return True + + +def instance_extra_metrics(field, value): + return get_default_field_value(field, value) + + +def instance_metrics(field, value): + return get_default_field_value(field, value) def instance_min_collection_interval(field, value): return 15 +def instance_namespace(field, value): + return get_default_field_value(field, value) + + def instance_password(field, value): return get_default_field_value(field, value) +def instance_server(field, value): + return get_default_field_value(field, value) + + +def instance_server_tag(field, value): + return get_default_field_value(field, value) + + def instance_service(field, value): return get_default_field_value(field, value) diff --git a/iis/datadog_checks/iis/config_models/instance.py b/iis/datadog_checks/iis/config_models/instance.py index 4a633d74d1291..c9d4439286061 100644 --- a/iis/datadog_checks/iis/config_models/instance.py +++ b/iis/datadog_checks/iis/config_models/instance.py @@ -3,9 +3,9 @@ # Licensed under a 3-clause BSD style license (see LICENSE) from __future__ import annotations -from typing import Optional, Sequence +from typing import Literal, Mapping, Optional, Sequence, Union -from pydantic import BaseModel, root_validator, validator +from pydantic import BaseModel, Extra, Field, root_validator, validator from datadog_checks.base.utils.functions import identity from datadog_checks.base.utils.models import validation @@ -13,19 +13,89 @@ from . import defaults, validators +class Counter(BaseModel): + class Config: + extra = Extra.allow + allow_mutation = False + + aggregate: Optional[Union[bool, Literal['only']]] + average: Optional[bool] + metric_name: Optional[str] + name: Optional[str] + type: Optional[str] + + +class InstanceCounts(BaseModel): + class Config: + allow_mutation = False + + monitored: Optional[str] + total: Optional[str] + unique: Optional[str] + + +class ExtraMetrics(BaseModel): + class Config: + allow_mutation = False + + counters: Sequence[Mapping[str, Union[str, Counter]]] + exclude: Optional[Sequence[str]] + include: Optional[Sequence[str]] + instance_counts: Optional[InstanceCounts] + name: str + tag_name: Optional[str] + use_localized_counters: Optional[bool] + + +class Counter1(BaseModel): + class Config: + extra = Extra.allow + allow_mutation = False + + aggregate: Optional[Union[bool, Literal['only']]] + average: Optional[bool] + metric_name: Optional[str] + name: Optional[str] + type: Optional[str] + + +class InstanceCounts1(BaseModel): + class Config: + allow_mutation = False + + monitored: Optional[str] + total: Optional[str] + unique: Optional[str] + + +class Metrics(BaseModel): + class Config: + allow_mutation = False + + counters: Sequence[Mapping[str, Union[str, Counter1]]] + exclude: Optional[Sequence[str]] + include: Optional[Sequence[str]] + instance_counts: Optional[InstanceCounts1] + name: str + tag_name: Optional[str] + use_localized_counters: Optional[bool] + + class InstanceConfig(BaseModel): class Config: allow_mutation = False - additional_metrics: Optional[Sequence[Sequence[str]]] app_pools: Optional[Sequence[str]] - counter_data_types: Optional[Sequence[str]] disable_generic_tags: Optional[bool] empty_default_hostname: Optional[bool] - host: str - is_2008: Optional[bool] + enable_health_service_check: Optional[bool] + extra_metrics: Optional[Mapping[str, ExtraMetrics]] + metrics: Optional[Mapping[str, Metrics]] min_collection_interval: Optional[float] + namespace: Optional[str] = Field(None, regex='\\w*') password: Optional[str] + server: Optional[str] + server_tag: Optional[str] service: Optional[str] sites: Optional[Sequence[str]] tags: Optional[Sequence[str]] diff --git a/iis/datadog_checks/iis/config_models/shared.py b/iis/datadog_checks/iis/config_models/shared.py index d1c10eced36ca..f5f839962daf7 100644 --- a/iis/datadog_checks/iis/config_models/shared.py +++ b/iis/datadog_checks/iis/config_models/shared.py @@ -18,6 +18,7 @@ class Config: allow_mutation = False service: Optional[str] + use_localized_counters: Optional[bool] @root_validator(pre=True) def _initial_validation(cls, values): diff --git a/iis/datadog_checks/iis/data/conf.yaml.example b/iis/datadog_checks/iis/data/conf.yaml.example index 066c9815ad3ed..ef247145228a6 100644 --- a/iis/datadog_checks/iis/data/conf.yaml.example +++ b/iis/datadog_checks/iis/data/conf.yaml.example @@ -2,6 +2,12 @@ # init_config: + ## @param use_localized_counters - boolean - optional - default: false + ## Whether or not performance object and counter names should refer to their + ## locale-specific versions rather than by their English name. + # + # use_localized_counters: false + ## @param service - string - optional ## Attach the tag `service:` to every metric, event, and service check emitted by this integration. ## @@ -13,26 +19,7 @@ init_config: # instances: - ## @param host - string - required - ## By default, this check runs against a single instance - the current - ## machine that the Agent is running on. It checks the PDH (Performance - ## Data Helper) performance counters for IIS on that machine. - ## - ## "." means the current host, any other value makes the Agent attempt to connect to a remote host. - ## Note: Remote access requires additional permissions. - # - - host: . - - ## @param username - string - optional - ## The username from the credentials needed to connect to the host. - # - # username: - - ## @param password - string - optional - ## The password from the credentials needed to connect to the host. - # - # password: - + - ## @param sites - list of strings - optional ## The `sites` parameter allows you to specify a list of sites you want to ## read metrics from. With sites specified, metrics are tagged with the @@ -53,40 +40,101 @@ instances: # - # - - ## @param is_2008 - boolean - optional - default: false - ## Because of a typo in IIS6/7 (typically on W2K8) where perfmon reports TotalBytesTransferred as - ## TotalBytesTransfered, you may have to enable this to grab the IIS metrics in that environment. + ## @param server - string - optional + ## The server with which to connect, defaulting to the local machine. # - # is_2008: false + # server: - ## @param additional_metrics - list of lists - optional - ## The additional metrics is a list of items that represent additional counters to collect. - ## Each item is a list of strings, formatted as follows: + ## @param username - string - optional + ## The username used to connect to the `server`. + # + # username: + + ## @param password - string - optional + ## The password of `username`. + # + # password: + + ## @param enable_health_service_check - boolean - optional - default: true + ## Whether or not to send a service check named `.windows.perf.health` which reports + ## the health of the `server`. + # + # enable_health_service_check: true + + ## @param server_tag - string - optional + ## The name used for tagging `server`. The value defined here replaces the `server:` tag key. + # + # server_tag: + + ## @param extra_metrics - mapping - optional + ## This mapping defines which metrics to collect from the performance + ## counters on the `server`. For more information, see: + ## https://docs.microsoft.com/en-us/windows/win32/perfctrs/about-performance-counters ## - ## ['', , '', , ] + ## The top-level keys are the names of the desired performance objects: ## - ## is the name of the PDH counter set (the name of the counter). - ## is the specific counter instance to collect, for example - ## "Default Web Site". Specify 'none' for all instances of - ## the counter. - ## is the individual counter to report. - ## is the name that displays in Datadog. - ## is from the standard choices for all Agent checks, such as gauge, - ## rate, histogram, or count. - # - # additional_metrics: - # - [Web Service, none, CGI Requests/sec, iis.httpd_request_method.cgi, gauge] - - ## @param counter_data_types - list of strings - optional - ## counter_data_types is a list of , elements that - ## allow the precision in which counters are queried on a per metric basis. - ## : The name of your metric - ## : The type of your metric (int or float) + ## metrics: + ## System: + ## : ... + ## : ... + ## LogicalDisk: + ## : ... + ## : ... + ## + ## The available performance object options are: + ## + ## name (required): This becomes the prefix of all metrics submitted for each counter. + ## counters (required): This is the list of counters to collect. + ## tag_name: This is the name of the tag used for instances. For example, if the tag name for + ## the `LogicalDisk` performance object is `disk`, a possible tag would be `disk:C`. + ## If not set, the default tag name is `instance`. + ## include: This is the list of regular expressions used to select which instances to monitor. + ## If not set, all instances are monitored. + ## exclude: This is the list of regular expressions used to select which instances to ignore. + ## If not set, no instances are ignored. Note: `_Total` instances are always ignored. + ## instance_counts: This is a mapping used to select the count of instances to submit, where each + ## key is a count type and the value is the metric name to use, ignoring `name`. + ## The `total` count type represents the total number of encountered instances. + ## The `monitored` count type represents the number of monitored instances after + ## `include`/`exclude` filtering. The `unique` count type represents the number + ## of unique instance names that are monitored. + ## use_localized_counters: Whether or not performance object and counter names should refer to their + ## locale-specific versions rather than by their English name. This overrides + ## any defined value in `init_config`. + ## + ## The key for each counter object represents the name of the desired counter. + ## Counters may be defined in the following ways: + ## + ## 1. If a value is a string, then it represents the suffix of the sent metric name, for example: + ## + ## counters: + ## - '% Free Space': usable + ## - Current Disk Queue Length: queue_length.current + ## + ## 2. If a value is a mapping, then it must have a `name` key that represents the suffix of the + ## sent metric name, for example: + ## + ## counters: + ## - '% Free Space': + ## name: usable + ## - Current Disk Queue Length: + ## name: queue_length.current + ## + ## The available counter options are: + ## + ## type: This represents how the metric is handled, defaulting to `gauge`. The available types are: + ## gauge, rate, count, monotonic_count, service_check, temporal_percent, time_elapsed + ## average: When there are multiple values for the same instance name (e.g. multiple processes + ## spawned with the same name) the check submits the sum. Setting this option to `true` + ## instructs the check to calculate the average instead. + ## aggregate: Whether or not to send an additional metric that is the aggregation of all values for + ## every monitored instance. If `average` is set to `true` the check submits the average as + ## a metric suffixed by `avg`, otherwise it submits the sum as a metric suffixed by `sum`. + ## If this is set to `only`, the check does not submit a metric per instance. + ## metric_name: This represents the full metric name in lieu of a `name` key and is not be prefixed by + ## the parent object's `name` key. # - # counter_data_types: - # - , - # - processor.time,int - # - processor.user.time,float + # extra_metrics: {} ## @param tags - list of strings - optional ## A list of tags to attach to every metric and service check emitted by this instance.