diff --git a/programs/server/Server.cpp b/programs/server/Server.cpp index 6b5aa1ac0b2..58391c2b755 100644 --- a/programs/server/Server.cpp +++ b/programs/server/Server.cpp @@ -296,6 +296,7 @@ namespace CurrentMetrics extern const Metric MergesMutationsMemoryTracking; extern const Metric MaxDDLEntryID; extern const Metric MaxPushedDDLEntryID; + extern const Metric StartupScriptsExecutionState; } namespace ProfileEvents @@ -366,6 +367,14 @@ namespace ErrorCodes } +enum StartupScriptsExecutionState : CurrentMetrics::Value +{ + NotFinished = 0, + Success = 1, + Failure = 2, +}; + + static std::string getCanonicalPath(std::string && path) { Poco::trimInPlace(path); @@ -782,9 +791,12 @@ void loadStartupScripts(const Poco::Util::AbstractConfiguration & config, Contex startup_context->makeQueryContext(); executeQuery(read_buffer, write_buffer, true, startup_context, callback, QueryFlags{ .internal = true }, std::nullopt, {}); } + + CurrentMetrics::set(CurrentMetrics::StartupScriptsExecutionState, StartupScriptsExecutionState::Success); } catch (...) { + CurrentMetrics::set(CurrentMetrics::StartupScriptsExecutionState, StartupScriptsExecutionState::Failure); tryLogCurrentException(log, "Failed to parse startup scripts file"); } } diff --git a/src/Common/CurrentMetrics.cpp b/src/Common/CurrentMetrics.cpp index fa3c383cc64..8c3f2a442c4 100644 --- a/src/Common/CurrentMetrics.cpp +++ b/src/Common/CurrentMetrics.cpp @@ -356,6 +356,8 @@ M(SharedDatabaseCatalogTablesInLocalDropDetachQueue, "Number of tables in the queue for local drop or detach in Shared Catalog.") \ \ M(MergeTreeIndexGranularityInternalArraysTotalSize, "The total size of all internal arrays in Merge Tree index granularity objects in bytes.") \ + \ + M(StartupScriptsExecutionState, "State of startup scripts execution: 0 = not finished, 1 = success, 2 = failure.") \ #ifdef APPLY_FOR_EXTERNAL_METRICS #define APPLY_FOR_METRICS(M) APPLY_FOR_BUILTIN_METRICS(M) APPLY_FOR_EXTERNAL_METRICS(M) diff --git a/tests/integration/test_startup_scripts_execution_state/__init__.py b/tests/integration/test_startup_scripts_execution_state/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_startup_scripts_execution_state/config/bad_script.xml b/tests/integration/test_startup_scripts_execution_state/config/bad_script.xml new file mode 100644 index 00000000000..1306cc116c9 --- /dev/null +++ b/tests/integration/test_startup_scripts_execution_state/config/bad_script.xml @@ -0,0 +1,10 @@ + + + + SELECT 42; + + + SELECT * FROM non_existent_table; + + + diff --git a/tests/integration/test_startup_scripts_execution_state/config/good_script.xml b/tests/integration/test_startup_scripts_execution_state/config/good_script.xml new file mode 100644 index 00000000000..f16f800eb6c --- /dev/null +++ b/tests/integration/test_startup_scripts_execution_state/config/good_script.xml @@ -0,0 +1,11 @@ + + + + SELECT 0; + SELECT * FROM non_existent_table; + + + SELECT 42; + + + diff --git a/tests/integration/test_startup_scripts_execution_state/config/users.xml b/tests/integration/test_startup_scripts_execution_state/config/users.xml new file mode 100644 index 00000000000..c5de0b6819c --- /dev/null +++ b/tests/integration/test_startup_scripts_execution_state/config/users.xml @@ -0,0 +1,8 @@ + + + + default + + + + \ No newline at end of file diff --git a/tests/integration/test_startup_scripts_execution_state/test.py b/tests/integration/test_startup_scripts_execution_state/test.py new file mode 100644 index 00000000000..f00026df2ff --- /dev/null +++ b/tests/integration/test_startup_scripts_execution_state/test.py @@ -0,0 +1,56 @@ +import random +import string +import time +from enum import Enum + +import pytest + +from helpers.cluster import ClickHouseCluster + +cluster = ClickHouseCluster(__file__) +good = cluster.add_instance( + "good", + main_configs=["config/users.xml", "config/good_script.xml"], + stay_alive=True, +) +bad = cluster.add_instance( + "bad", + main_configs=["config/users.xml", "config/bad_script.xml"], + stay_alive=True, +) + + +@pytest.fixture(scope="module") +def start_cluster(): + try: + cluster.start() + yield cluster + finally: + cluster.shutdown() + + +def test_startup_execution_state(start_cluster): + """ + Making sure that the StartupScriptsExecutionState metric is set correctly. + """ + + STATE_SUCCESS = 1 + STATE_FAILURE = 2 + + assert ( + int( + good.query( + "SELECT value FROM system.metrics WHERE metric = 'StartupScriptsExecutionState'" + ).strip() + ) + == STATE_SUCCESS + ) + + assert ( + int( + bad.query( + "SELECT value FROM system.metrics WHERE metric = 'StartupScriptsExecutionState'" + ).strip() + ) + == STATE_FAILURE + )