Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partially remove db exist check if ignore db is false #17300

Merged
merged 18 commits into from
Apr 4, 2024
4 changes: 3 additions & 1 deletion sqlserver/assets/configuration/spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,9 @@ files:
type: string
example: master
- name: ignore_missing_database
description: If the DB specified doesn't exist on the server then don't do the check
description: |
DEPRECATED - use `database_autodiscovery` instead, when database name is uncertain.
If the DB specified doesn't exist on the server then don't do the check
value:
type: boolean
example: false
Expand Down
1 change: 1 addition & 0 deletions sqlserver/changelog.d/17300.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove db exist check if ignore_missing_database is set to false. In this case throw SQLConnectionError instead of ConfigurationError when database does not exist.
6 changes: 6 additions & 0 deletions sqlserver/datadog_checks/sqlserver/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ def __init__(self, init_config, instance, log):
self.include_index_usage_metrics_tempdb: bool = is_affirmative(
instance.get('include_index_usage_metrics_tempdb', False)
)
self.ignore_missing_database = is_affirmative(instance.get("ignore_missing_database", False))
if self.ignore_missing_database:
self.log.warning(
"The parameter 'ignore_missing_database' is deprecated"
"if you are unsure about the database name please use 'database_autodiscovery'"
)

# DBM
self.dbm_enabled: bool = is_affirmative(instance.get('dbm', False))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ instances:
# proc_only_if_database: master

## @param ignore_missing_database - boolean - optional - default: false
## DEPRECATED - use `database_autodiscovery` instead, when database name is uncertain.
## If the DB specified doesn't exist on the server then don't do the check
#
# ignore_missing_database: false
Expand Down
48 changes: 22 additions & 26 deletions sqlserver/datadog_checks/sqlserver/sqlserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import six
from cachetools import TTLCache

from datadog_checks.base import AgentCheck, ConfigurationError
from datadog_checks.base import AgentCheck
from datadog_checks.base.config import is_affirmative
from datadog_checks.base.utils.db import QueryExecutor, QueryManager
from datadog_checks.base.utils.db.utils import default_json_event_encoding, resolve_db_host, tracked_query
Expand Down Expand Up @@ -332,31 +332,27 @@ def initialize_connection(self):
def make_metric_list_to_collect(self):
# Pre-process the list of metrics to collect
try:
# check to see if the database exists before we try any connections to it
db_exists, context = self.connection.check_database()
if db_exists:
if self.instance.get('stored_procedure') is None:
with self.connection.open_managed_default_connection():
with self.connection.get_managed_cursor() as cursor:
self.autodiscover_databases(cursor)
self._make_metric_list_to_collect(self._config.custom_metrics)
else:
# How much do we care that the DB doesn't exist?
ignore = is_affirmative(self.instance.get("ignore_missing_database", False))
if ignore is not None and ignore:
# not much : we expect it. leave checks disabled
self.do_check = False
self.log.warning("Database %s does not exist. Disabling checks for this instance.", context)
else:
# yes we do. Keep trying
msg = "Database {} does not exist. Please resolve invalid database and restart agent".format(
context
)
raise ConfigurationError(msg)

except SQLConnectionError as e:
self.log.exception("Error connecting to database: %s", e)
except ConfigurationError:
if self._config.ignore_missing_database:
# self.connection.check_database() will try to connect to 'master'.
# If this is an Azure SQL Database this function will throw.
# For this reason we avoid calling self.connection.check_database()
# for this config as it will be a false negative.
engine_edition = self.static_info_cache.get(STATIC_INFO_ENGINE_EDITION)
if not is_azure_sql_database(engine_edition):
# Do the database exist check that will allow to disable _check as a whole
# as otherwise the first call to open_managed_default_connection will throw the
# SQLConnectionError.
db_exists, context = self.connection.check_database()
if not db_exists:
self.do_check = False
self.log.warning("Database %s does not exist. Disabling checks for this instance.", context)
return
if self.instance.get('stored_procedure') is None:
with self.connection.open_managed_default_connection():
with self.connection.get_managed_cursor() as cursor:
self.autodiscover_databases(cursor)
self._make_metric_list_to_collect(self._config.custom_metrics)
except SQLConnectionError:
raise
except Exception as e:
self.log.exception("Initialization exception %s", e)
Expand Down
2 changes: 2 additions & 0 deletions sqlserver/tests/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ def test_check_index_usage_metrics(
):
instance_docker_metrics['database'] = 'datadog_test'
instance_docker_metrics['include_index_usage_metrics'] = True
instance_docker_metrics['ignore_missing_database'] = True

# Cause an index seek
bob_conn.execute_with_retries(
Expand Down Expand Up @@ -379,6 +380,7 @@ def test_check_incr_fraction_metrics(
bob_conn_raw,
):
instance_docker_metrics['database'] = 'datadog_test'
instance_docker_metrics['ignore_missing_database'] = True
sqlserver_check = SQLServer(CHECK_NAME, init_config, [instance_docker_metrics])

sqlserver_check.run()
Expand Down
17 changes: 10 additions & 7 deletions sqlserver/tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import mock
import pytest

from datadog_checks.base.errors import ConfigurationError
from datadog_checks.dev import EnvVars
from datadog_checks.sqlserver import SQLServer
from datadog_checks.sqlserver.connection import split_sqlserver_host_port
Expand Down Expand Up @@ -43,8 +42,12 @@ def test_get_cursor(instance_docker):
def test_missing_db(instance_docker, dd_run_check):
instance = copy.copy(instance_docker)
instance['ignore_missing_database'] = False
with mock.patch('datadog_checks.sqlserver.connection.Connection.check_database', return_value=(False, 'db')):
with pytest.raises(ConfigurationError):

with mock.patch(
'datadog_checks.sqlserver.connection.Connection.open_managed_default_connection',
side_effect=SQLConnectionError(Exception("couldnt connect")),
):
with pytest.raises(SQLConnectionError):
check = SQLServer(CHECK_NAME, {}, [instance])
check.initialize_connection()
check.make_metric_list_to_collect()
Expand Down Expand Up @@ -79,13 +82,13 @@ def test_db_exists(get_cursor, mock_connect, instance_docker_defaults, dd_run_ch
instance = copy.copy(instance_docker_defaults)
# make sure check doesn't try to add metrics
instance['stored_procedure'] = 'fake_proc'
instance['ignore_missing_database'] = True

# check base case of lowercase for lowercase and case-insensitive db
check = SQLServer(CHECK_NAME, {}, [instance])
check.initialize_connection()
check.make_metric_list_to_collect()
assert check.do_check is True

# check all caps for case insensitive db
instance['database'] = 'MASTER'
check = SQLServer(CHECK_NAME, {}, [instance])
Expand All @@ -110,9 +113,9 @@ def test_db_exists(get_cursor, mock_connect, instance_docker_defaults, dd_run_ch
# check case sensitive but mismatched db
instance['database'] = 'cASEsENSITIVE2018'
check = SQLServer(CHECK_NAME, {}, [instance])
with pytest.raises(ConfigurationError):
check.initialize_connection()
check.make_metric_list_to_collect()
check.initialize_connection()
check.make_metric_list_to_collect()
assert check.do_check is False

# check offline but exists db
instance['database'] = 'Offlinedb'
Expand Down
Loading