|
6 | 6 | from clickhouse_connect.driver.exceptions import Error, OperationalError |
7 | 7 |
|
8 | 8 | from datadog_checks.base import ConfigurationError |
9 | | -from datadog_checks.clickhouse import ClickhouseCheck, advanced_queries |
| 9 | +from datadog_checks.clickhouse import ClickhouseCheck, advanced_queries, queries |
| 10 | +from datadog_checks.clickhouse.utils import cluster_aware_query |
10 | 11 |
|
11 | 12 | from .utils import ensure_csv_safe, parse_described_metrics, raise_error |
12 | 13 |
|
@@ -381,3 +382,76 @@ def test_database_hostname_ignores_reported_hostname_override(reported_hostname, |
381 | 382 | # reported_hostname honors the override when configured, otherwise the resolved host |
382 | 383 | assert check.reported_hostname == expected_reported_hostname |
383 | 384 | mock_resolve.assert_called_with(BASE_INSTANCE['server']) |
| 385 | + |
| 386 | + |
| 387 | +def test_cluster_aware_query_bulk_match_query(): |
| 388 | + """The cluster-aware variant reads all replicas and tags system.events per node.""" |
| 389 | + variant = cluster_aware_query(advanced_queries.SystemEvents) |
| 390 | + |
| 391 | + assert variant['query'] == ( |
| 392 | + "SELECT value, event, hostName() AS clickhouse_node FROM clusterAllReplicas('default', system.events)" |
| 393 | + ) |
| 394 | + assert variant['columns'][-1] == {'name': 'clickhouse_node', 'type': 'tag'} |
| 395 | + # The base query dict must not be mutated by building the variant. |
| 396 | + assert advanced_queries.SystemEvents['query'] == 'SELECT value, event FROM system.events' |
| 397 | + assert all(column['name'] != 'clickhouse_node' for column in advanced_queries.SystemEvents['columns']) |
| 398 | + |
| 399 | + |
| 400 | +def test_cluster_aware_query_preserves_where_clause(): |
| 401 | + """system.errors carries a WHERE clause that must survive in the cluster-aware variant.""" |
| 402 | + variant = cluster_aware_query(advanced_queries.SystemErrors) |
| 403 | + |
| 404 | + assert variant['query'] == ( |
| 405 | + "SELECT value, name, code, remote, hostName() AS clickhouse_node " |
| 406 | + "FROM clusterAllReplicas('default', system.errors) WHERE value > 0" |
| 407 | + ) |
| 408 | + assert variant['columns'][-1] == {'name': 'clickhouse_node', 'type': 'tag'} |
| 409 | + |
| 410 | + |
| 411 | +def test_cluster_aware_query_legacy_query(): |
| 412 | + """The helper builds a cluster-aware variant for a legacy query too.""" |
| 413 | + variant = cluster_aware_query(queries.SystemMetrics) |
| 414 | + |
| 415 | + assert variant['query'] == ( |
| 416 | + "SELECT value, metric, hostName() AS clickhouse_node FROM clusterAllReplicas('default', system.metrics)" |
| 417 | + ) |
| 418 | + assert variant['columns'][-1] == {'name': 'clickhouse_node', 'type': 'tag'} |
| 419 | + assert queries.SystemMetrics['query'] == 'SELECT value, metric FROM system.metrics' |
| 420 | + |
| 421 | + |
| 422 | +@pytest.mark.parametrize('use_advanced_queries', [True, False]) |
| 423 | +def test_get_queries_tags_system_tables_per_node_in_single_endpoint_mode(instance, use_advanced_queries): |
| 424 | + instance = { |
| 425 | + **instance, |
| 426 | + 'single_endpoint_mode': True, |
| 427 | + 'use_advanced_queries': use_advanced_queries, |
| 428 | + 'use_legacy_queries': not use_advanced_queries, |
| 429 | + } |
| 430 | + check = ClickhouseCheck('clickhouse', {}, [instance]) |
| 431 | + check._server_version = '24.8' |
| 432 | + |
| 433 | + cluster_aware = [q for q in check.get_queries() if 'clusterAllReplicas' in q['query']] |
| 434 | + |
| 435 | + # system.events, system.metrics, system.asynchronous_metrics (+ system.errors / events-to-deprecate) |
| 436 | + assert cluster_aware |
| 437 | + for query in cluster_aware: |
| 438 | + assert 'hostName() AS clickhouse_node' in query['query'] |
| 439 | + assert query['columns'][-1] == {'name': 'clickhouse_node', 'type': 'tag'} |
| 440 | + |
| 441 | + # system.parts/replicas/dictionaries use GROUP BY and are intentionally left untouched here. |
| 442 | + if not use_advanced_queries: |
| 443 | + assert any(q is queries.SystemParts for q in check.get_queries()) |
| 444 | + |
| 445 | + |
| 446 | +@pytest.mark.parametrize('use_advanced_queries', [True, False]) |
| 447 | +def test_get_queries_uses_base_queries_for_direct_connection(instance, use_advanced_queries): |
| 448 | + instance = { |
| 449 | + **instance, |
| 450 | + 'single_endpoint_mode': False, |
| 451 | + 'use_advanced_queries': use_advanced_queries, |
| 452 | + 'use_legacy_queries': not use_advanced_queries, |
| 453 | + } |
| 454 | + check = ClickhouseCheck('clickhouse', {}, [instance]) |
| 455 | + check._server_version = '24.8' |
| 456 | + |
| 457 | + assert all('clusterAllReplicas' not in q['query'] for q in check.get_queries()) |
0 commit comments