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
+ )