Skip to content
Merged
4 changes: 4 additions & 0 deletions docs/en/operations/opentelemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ The table must be enabled in the server configuration, see the `opentelemetry_sp

The tags or attributes are saved as two parallel arrays, containing the keys and values. Use [ARRAY JOIN](../sql-reference/statements/select/array-join.md) to work with them.

## Log-query-settings
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sharathks118 Without a link to the corresponding setting in "settings.md", readers will be confused by "Log-query-settings" and below description.


ClickHouse allows you to log changes to query settings during query execution. When enabled, any modifications made to query settings will be recorded in the OpenTelemetry span log. This feature is particularly useful in production environments for tracking configuration changes that may affect query performance.

## Integration with monitoring systems

At the moment, there is no ready tool that can export the tracing data from ClickHouse to a monitoring system.
Expand Down
8 changes: 8 additions & 0 deletions docs/en/operations/settings/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,14 @@ Default value: 0

Allow non-const timezone arguments in certain time-related functions like toTimeZone(), fromUnixTimestamp*(), snowflakeToDateTime*()

## log_query_settings {#log-query-settings}

Type: Bool

Default value: 1

Log query settings into the query_log and opentelemetry_span_log.

## allow_nondeterministic_mutations {#allow_nondeterministic_mutations}

Type: Bool
Expand Down
12 changes: 11 additions & 1 deletion src/Core/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2700,7 +2700,7 @@ The maximum read speed in bytes per second for particular backup on server. Zero
Log query performance statistics into the query_log, query_thread_log and query_views_log.
)", 0) \
M(Bool, log_query_settings, true, R"(
Log query settings into the query_log.
Log query settings into the query_log and OpenTelemetry span log.
)", 0) \
M(Bool, log_query_threads, false, R"(
Setting up query threads logging.
Expand Down Expand Up @@ -6200,6 +6200,16 @@ std::vector<std::string_view> Settings::getUnchangedNames() const
return setting_names;
}

std::vector<std::string_view> Settings::getChangedNames() const
{
std::vector<std::string_view> setting_names;
for (const auto & setting : impl->allChanged())
{
setting_names.emplace_back(setting.getName());
}
return setting_names;
}

void Settings::dumpToSystemSettingsColumns(MutableColumnsAndConstraints & params) const
{
MutableColumns & res_columns = params.res_columns;
Expand Down
1 change: 1 addition & 0 deletions src/Core/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct Settings
std::vector<std::string_view> getAllRegisteredNames() const;
std::vector<std::string_view> getChangedAndObsoleteNames() const;
std::vector<std::string_view> getUnchangedNames() const;
std::vector<std::string_view> getChangedNames() const;

void dumpToSystemSettingsColumns(MutableColumnsAndConstraints & params) const;
void dumpToMapColumn(IColumn * column, bool changed_only = true) const;
Expand Down
20 changes: 20 additions & 0 deletions src/Interpreters/executeQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <Common/MemoryTrackerBlockerInThread.h>
#include <Common/SensitiveDataMasker.h>
#include <Common/FailPoint.h>
#include <Common/FieldVisitorToString.h>

#include <Interpreters/AsynchronousInsertQueue.h>
#include <Interpreters/Cache/QueryCache.h>
Expand Down Expand Up @@ -564,6 +565,25 @@ void logQueryFinish(
query_span->addAttributeIfNotZero("clickhouse.written_rows", elem.written_rows);
query_span->addAttributeIfNotZero("clickhouse.written_bytes", elem.written_bytes);
query_span->addAttributeIfNotZero("clickhouse.memory_usage", elem.memory_usage);

if (context)
{
std::string user_name = context->getUserName();
query_span->addAttribute("clickhouse.user", user_name);
}

if (settings[Setting::log_query_settings])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this feature is controlled by this setting, it's better to update docs and the setting description in the code to reflect this change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated documentation and setting descriptions

{
auto changed_settings_names = settings.getChangedNames();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already have this in settings.changes(). No need to add a new function and call .get() every time

for (const auto & name : changed_settings_names)
{
Field value = settings.get(name);
String value_str = convertFieldToString(value);

query_span->addAttribute(fmt::format("clickhouse.setting.{}", name), value_str);

}
}
query_span->finish();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
{"query":"show databases format Null\n "}
{"query":"insert into opentelemetry_test values","read_rows":"3","written_rows":"3"}
{"query":"select * from opentelemetry_test format Null\n ","read_rows":"3","written_rows":""}
{"query":"SELECT * FROM opentelemetry_test FORMAT Null\n ","read_rows":"3","written_rows":""}
{"min_compress_block_size":"present","max_block_size":"present","max_execution_time":"present"}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,37 @@ ${CLICKHOUSE_CLIENT} -q "
;"
}

function check_query_settings()
{
result=$(${CLICKHOUSE_CLIENT} -q "
SYSTEM FLUSH LOGS;
SELECT attribute['clickhouse.setting.min_compress_block_size'],
attribute['clickhouse.setting.max_block_size'],
attribute['clickhouse.setting.max_execution_time']
FROM system.opentelemetry_span_log
WHERE finish_date >= yesterday()
AND operation_name = 'query'
AND attribute['clickhouse.query_id'] = '${1}'
FORMAT JSONEachRow;
")

local min_present="not found"
local max_present="not found"
local execution_time_present="not found"

if [[ $result == *"min_compress_block_size"* ]]; then
min_present="present"
fi
if [[ $result == *"max_block_size"* ]]; then
max_present="present"
fi
if [[ $result == *"max_execution_time"* ]]; then
execution_time_present="present"
fi

echo "{\"min_compress_block_size\":\"$min_present\",\"max_block_size\":\"$max_present\",\"max_execution_time\":\"$execution_time_present\"}"
}

#
# Set up
#
Expand Down Expand Up @@ -73,6 +104,11 @@ query_id=$(${CLICKHOUSE_CLIENT} -q "select generateUUIDv4()");
execute_query $query_id 'select * from opentelemetry_test format Null'
check_query_span $query_id

# Test 5: A normal select query with a setting
query_id=$(${CLICKHOUSE_CLIENT} -q "SELECT generateUUIDv4() SETTINGS max_execution_time=3600")
execute_query "$query_id" 'SELECT * FROM opentelemetry_test FORMAT Null'
check_query_span "$query_id"
check_query_settings "$query_id" "max_execution_time"

#
# Tear down
Expand Down