Skip to content

Commit 3c4e189

Browse files
[clickhouse] Skip emitting empty storage_health payloads (#23553)
* [clickhouse][dbm] Skip emitting empty storage_health payloads Skip the database_monitoring_query_activity emission when every parts-and-merges collection (parts, merges, mutations, replication queue, detached parts, thresholds) is empty. This is the case for fresh ClickHouse Cloud instances with no user data and restricted system tables, and for transient total-collection-failure scenarios. Empty storage_health payloads previously wedged dbm-events-processor partitions on the dd-go side; that processor is being fixed independently in DataDog/dd-go#234748. This change also avoids emitting one useless Kafka message per collection cycle for any genuinely-idle/empty instance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Add changelog entry for PR #23553 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Add end-to-end test for skipped emission when all collectors return empty Pins the wiring between _collect_and_emit and _emit_events for the case where every collection query fails or returns no rows, which is the scenario that fires when all queries hit exceptions (auth/network) or on a fresh, restricted ClickHouse Cloud instance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent bf6a3c5 commit 3c4e189

3 files changed

Lines changed: 42 additions & 1 deletion

File tree

clickhouse/changelog.d/23553.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Skip emitting empty storage_health payloads when every parts-and-merges collection is empty.

clickhouse/datadog_checks/clickhouse/parts_and_merges.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,8 @@ def _emit_events(
818818
thresholds: list[dict] | None = None,
819819
) -> None:
820820
"""Emit a per-cycle row-level payload consumed by dbm-events-processor."""
821+
if not (parts or merges or mutations or replication_queue or detached_parts or thresholds):
822+
return
821823
now_ms = int(time.time() * 1000)
822824
payload = {
823825
"host": self._check.reported_hostname,

clickhouse/tests/test_parts_and_merges.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,12 +856,27 @@ def test_emit_events_uses_query_activity_channel_not_metadata(check):
856856
mock.patch('datadog_checks.clickhouse.parts_and_merges.datadog_agent') as agent_mock,
857857
):
858858
agent_mock.get_version.return_value = '7.64.0'
859-
job._emit_events([], [], [], [], [])
859+
job._emit_events(_collected_parts(), [], [], [], [])
860860

861861
activity_mock.assert_called_once()
862862
metadata_mock.assert_not_called()
863863

864864

865+
def test_emit_events_skips_when_all_collections_empty(check):
866+
job = check.parts_and_merges
867+
job.tags = ['test:clickhouse']
868+
job._tags_no_db = ['test:clickhouse']
869+
870+
with (
871+
mock.patch.object(check, 'database_monitoring_query_activity') as activity_mock,
872+
mock.patch('datadog_checks.clickhouse.parts_and_merges.datadog_agent') as agent_mock,
873+
):
874+
agent_mock.get_version.return_value = '7.64.0'
875+
job._emit_events([], [], [], [], [], [])
876+
877+
activity_mock.assert_not_called()
878+
879+
865880
# -----------------------------------------------------------------------------
866881
# Error handling
867882
# -----------------------------------------------------------------------------
@@ -907,6 +922,29 @@ def test_collect_and_emit_runs_with_partial_failures(check):
907922
assert payload['clickhouse']['active_merges'] == _collected_merges()
908923

909924

925+
def test_collect_and_emit_skips_when_all_collectors_empty(check):
926+
job = check.parts_and_merges
927+
job.tags = ['test:clickhouse']
928+
job._tags_no_db = ['test:clickhouse']
929+
930+
with (
931+
mock.patch.object(job, '_collect_parts', return_value=[]),
932+
mock.patch.object(job, '_collect_merges', return_value=[]),
933+
mock.patch.object(job, '_collect_mutations', return_value=[]),
934+
mock.patch.object(job, '_collect_mutations_aggregated', return_value=[]),
935+
mock.patch.object(job, '_collect_replication_queue', return_value=[]),
936+
mock.patch.object(job, '_collect_replication_queue_aggregated', return_value=[]),
937+
mock.patch.object(job, '_collect_detached_parts', return_value=[]),
938+
mock.patch.object(job, '_collect_thresholds', return_value=[]),
939+
mock.patch.object(check, 'database_monitoring_query_activity') as activity_mock,
940+
mock.patch('datadog_checks.clickhouse.parts_and_merges.datadog_agent') as agent_mock,
941+
):
942+
agent_mock.get_version.return_value = '7.64.0'
943+
job._collect_and_emit()
944+
945+
activity_mock.assert_not_called()
946+
947+
910948
# -----------------------------------------------------------------------------
911949
# Cluster routing
912950
# -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)