This is an automated email from the ASF dual-hosted git repository.
csringhofer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git
The following commit(s) were added to refs/heads/master by this push:
new 2ac5a24dc IMPALA-14455: Cleanup OpenTelemetry Tracing Startup Flags
2ac5a24dc is described below
commit 2ac5a24dc0cfc9c9e7a1fc86cccf94cd1a2900af
Author: jasonmfehr <[email protected]>
AuthorDate: Thu Sep 18 15:40:38 2025 -0700
IMPALA-14455: Cleanup OpenTelemetry Tracing Startup Flags
Fixes several issues with the OpenTelemetry tracing startup flags:
1. otel_trace_beeswax -- Removes this hidden flag which enabled
tracing of queries submitted over Beeswax. Since this protocol is
deprecated and no tests assert the traces generated by Beeswax
queries, this flag was removed to eliminate an extra check when
determining if OpenTelemetry tracing should be enabled.
2. otel_trace_tls_minimum_version -- Fixes parsing of this flag's
value. This flag is in the format "tlsv1.2" or "tlsv1.3", but the
OpenTelemetry C++ SDK expects the minimum TLS version to be in the
format "1.2" or "1.3". The code now removes the "tlsv" prefix before
passing the value to the OpenTelemetry C++ SDK.
3. otel_trace_tls_insecure_skip_verify -- Fixes the guidance to only
set this flag to true in dev/testing.
Adds ctest tests for the functions that configure the TraceProvider
singleton to ensure startup flags are correctly parsed and applied.
Modifies the http_exporter_config and init_otel_tracer function
signatures in otel.cc to return the actual object they create instead
of a Status since these functions only ever returned OK.
Updates the OpenTelemetry collector docker-compose file to support
the collector receiving traces over both HTTP and HTTPS. This setup
is used to manually smoke test the integration from Impala to an
OpenTelemetry collector.
Change-Id: Ie321fa37c0fd260f783dc6cf47924d53a06d82ea
Reviewed-on: http://gerrit.cloudera.org:8080/23440
Tested-by: Impala Public Jenkins <[email protected]>
Reviewed-by: Joe McDonnell <[email protected]>
---
be/src/observe/otel-flags-trace.cc | 14 +-
be/src/observe/otel-test.cc | 287 +++++++++++++++++++--
be/src/observe/otel.cc | 142 ++++++----
be/src/observe/otel.h | 22 +-
be/src/runtime/exec-env.cc | 2 +-
be/src/testutil/localhost.key | 27 ++
be/src/testutil/localhost.pem | 20 ++
testdata/bin/otel-collector/README.md | 25 +-
testdata/bin/otel-collector/docker-compose.yml | 4 +-
.../{otel-config.yml => otel-config-http.yml} | 0
.../{otel-config.yml => otel-config-https.yml} | 5 +-
11 files changed, 462 insertions(+), 86 deletions(-)
diff --git a/be/src/observe/otel-flags-trace.cc
b/be/src/observe/otel-flags-trace.cc
index 001adb401..e116548d1 100644
--- a/be/src/observe/otel-flags-trace.cc
+++ b/be/src/observe/otel-flags-trace.cc
@@ -61,10 +61,6 @@ DEFINE_validator(otel_trace_exporter, [](const char*
flagname, const string& val
return false;
}); // flag otel_trace_exporter
-DEFINE_bool_hidden(otel_trace_beeswax, false, "Specifies whether or not to
trace queries "
- "submitted via the Beeswax protocol. This flag is hidden because tracing
Beeswax "
- "queries is not supported.");
-
//
// Start of HTTP related flags.
//
@@ -160,7 +156,8 @@ DEFINE_validator(otel_trace_ca_cert_string, [](const char*
flagname,
DEFINE_string(otel_trace_tls_minimum_version, "", "String containing the
minimum allowed "
- "TLS version, if not specified, defaults to the overall minimum TLS
version.");
+ "TLS version the OpenTelemetry SDK will use when communicating with the
collector. "
+ "If empty, will use the value of the 'ssl_minimum_version' flag.");
DEFINE_validator(otel_trace_tls_minimum_version, [](const char* flagname,
const string& value) {
if (value.empty() || value == impala::TLSVersions::TLSV1_2 || value ==
"tlsv1.3") {
@@ -172,13 +169,14 @@ DEFINE_validator(otel_trace_tls_minimum_version, [](const
char* flagname,
}); // flag otel_trace_tls_minimum_version
DEFINE_string(otel_trace_ssl_ciphers, "", "List of allowed TLS cipher suites
when using "
- "TLS 1.2, default to the value of Impala’s ssl_cipher_list startup flag.");
+ "TLS 1.2. If empty, defaults to the value of the 'ssl_cipher_list' startup
flag.");
DEFINE_string(otel_trace_tls_cipher_suites, "", "List of allowed TLS cipher
suites when "
- "using TLS 1.3, default to the value of Impala’s tls_ciphersuites startup
flag.");
+ "using TLS 1.3. If empty, defaults to the value of the 'tls_ciphersuites'
startup "
+ "flag.");
DEFINE_bool(otel_trace_tls_insecure_skip_verify, false, "If set to true, skips
"
- "verification of collector’s TLS certificate. This should only be set to
false for "
+ "verification of collector’s TLS certificate. This should only be set to
true for "
"development / testing");
//
// End of TLS related flags.
diff --git a/be/src/observe/otel-test.cc b/be/src/observe/otel-test.cc
index 0b5f04cb3..72af04394 100644
--- a/be/src/observe/otel-test.cc
+++ b/be/src/observe/otel-test.cc
@@ -17,21 +17,54 @@
#include "observe/otel.h"
+#include <chrono>
#include <string>
#include <string_view>
#include <boost/algorithm/string/replace.hpp>
#include <gtest/gtest.h>
#include "gutil/strings/substitute.h"
-
+#include <opentelemetry/exporters/otlp/otlp_file_exporter.h>
+#include <opentelemetry/exporters/otlp/otlp_http.h>
+#include <opentelemetry/exporters/otlp/otlp_http_exporter.h>
+#include <opentelemetry/exporters/otlp/otlp_http_exporter_options.h>
+#include <opentelemetry/sdk/common/global_log_handler.h>
+#include <opentelemetry/sdk/trace/batch_span_processor.h>
+#include <opentelemetry/sdk/trace/batch_span_processor_options.h>
+#include <opentelemetry/sdk/trace/simple_processor.h>
#include "gen-cpp/Query_types.h"
+#include "observe/otel-log-handler.h"
#include "testutil/scoped-flag-setter.h"
using namespace std;
using namespace impala;
+using namespace opentelemetry::sdk::common::internal_log;
+using namespace opentelemetry::sdk::trace;
+using namespace opentelemetry::exporter::otlp;
-DECLARE_bool(otel_trace_beeswax);
+DECLARE_bool(otel_debug);
+DECLARE_string(otel_trace_additional_headers);
+DECLARE_int32(otel_trace_batch_queue_size);
+DECLARE_int32(otel_trace_batch_max_batch_size);
+DECLARE_int32(otel_trace_batch_schedule_delay_ms);
+DECLARE_string(otel_trace_ca_cert_path);
+DECLARE_string(otel_trace_ca_cert_string);
DECLARE_string(otel_trace_collector_url);
+DECLARE_bool(otel_trace_compression);
+DECLARE_string(otel_trace_exporter);
+DECLARE_double(otel_trace_retry_policy_backoff_multiplier);
+DECLARE_double(otel_trace_retry_policy_initial_backoff_s);
+DECLARE_int32(otel_trace_retry_policy_max_attempts);
+DECLARE_int32(otel_trace_retry_policy_max_backoff_s);
+DECLARE_string(otel_trace_span_processor);
+DECLARE_string(otel_trace_ssl_ciphers);
+DECLARE_int32(otel_trace_timeout_s);
+DECLARE_string(otel_trace_tls_cipher_suites);
+DECLARE_bool(otel_trace_tls_insecure_skip_verify);
+DECLARE_string(otel_trace_tls_minimum_version);
+DECLARE_string(ssl_cipher_list);
+DECLARE_string(ssl_minimum_version);
+DECLARE_string(tls_ciphersuites);
TEST(OtelTest, QueriesTraced) {
const auto runtest = [](const string_view sql_str) -> void {
@@ -113,14 +146,6 @@ TEST(OtelTest, QueriesTraced) {
run_newline_test("INSERT", "INTO TABLE FOO");
run_newline_test("INVALIDATE", "METADATA FOO");
run_newline_test("WITH", "T1 AS SELECT * FROM FOO");
-
- // Beeswax queries are traced when the otel_trace_beeswax flag is set.
- {
- auto trace_beeswax_setter =
- ScopedFlagSetter<bool>::Make(&FLAGS_otel_trace_beeswax, true);
-
- EXPECT_TRUE(should_otel_trace_query("SELECT * FROM foo",
TSessionType::BEESWAX));
- }
}
TEST(OtelTest, QueriesNotTraced) {
@@ -170,16 +195,11 @@ TEST(OtelTest, QueriesNotTraced) {
runtest("--comment only\n");
runtest("--comment only\n--comment only 2");
runtest("--comment only\n--comment only 2\n");
- // TODO: Move to the QueriesTraced test case one IMPALA-14370 is fixed.
+ // TODO: Move to the QueriesTraced test case once IMPALA-14370 is fixed.
runtest(strings::Substitute("/*/ comment */select * from tbl"));
- // Beeswax queries are not traced unless the otel_trace_beeswax flag is set.
- {
- auto trace_beeswax_setter =
- ScopedFlagSetter<bool>::Make(&FLAGS_otel_trace_beeswax, false);
-
- EXPECT_FALSE(should_otel_trace_query("SELECT * FROM foo",
TSessionType::BEESWAX));
- }
+ // Beeswax queries are not traced.
+ EXPECT_FALSE(should_otel_trace_query("SELECT * FROM foo",
TSessionType::BEESWAX));
}
TEST(OtelTest, TLSEnabled) {
@@ -220,3 +240,234 @@ TEST(OtelTest, TLSNotEnabled) {
EXPECT_FALSE(test::otel_tls_enabled_for_testing());
}
}
+
+// Assert the default values of the OtlpHttpExporterOptions struct used to
configure the
+// OtlpHttpExporter.
+TEST(OtelTest, InitHttpDefaults) {
+ FLAGS_otel_trace_collector_url = "https://foo.com";
+ FLAGS_ssl_minimum_version = "tlsv1.0";
+ FLAGS_ssl_cipher_list = "ssl_ciphers";
+ FLAGS_tls_ciphersuites = "tls_ciphers";
+
+ OtlpHttpExporterOptions actual = test::get_http_exporter_config();
+
+ EXPECT_EQ("https://foo.com", actual.url);
+ EXPECT_EQ(HttpRequestContentType::kJson, actual.content_type);
+ EXPECT_EQ(false, actual.console_debug);
+ EXPECT_EQ(chrono::seconds(10), actual.timeout);
+ EXPECT_EQ(5, actual.retry_policy_max_attempts);
+ EXPECT_EQ(chrono::seconds(1), actual.retry_policy_initial_backoff);
+ EXPECT_EQ(chrono::duration<float>(5.0), actual.retry_policy_max_backoff);
+ EXPECT_EQ(2.0, actual.retry_policy_backoff_multiplier);
+ EXPECT_EQ("zlib", actual.compression);
+ EXPECT_EQ("1.0", actual.ssl_min_tls);
+ EXPECT_EQ("1.3", actual.ssl_max_tls);
+ EXPECT_EQ("ssl_ciphers", actual.ssl_cipher);
+ EXPECT_EQ("tls_ciphers", actual.ssl_cipher_suite);
+ EXPECT_EQ(false, actual.ssl_insecure_skip_verify);
+ EXPECT_EQ("", actual.ssl_ca_cert_path);
+ EXPECT_EQ("", actual.ssl_ca_cert_string);
+ EXPECT_EQ(0, actual.http_headers.size());
+ EXPECT_TRUE(actual.http_headers.empty());
+}
+
+// Assert the flags that customize the values of the OtlpHttpExporterOptions
struct used
+// to configure the OtlpHttpExporter.
+TEST(OtelTest, InitHttpOverrides) {
+ FLAGS_otel_trace_collector_url = "https://foo.com";
+ FLAGS_otel_trace_tls_minimum_version = "tlsv1.3";
+ FLAGS_otel_trace_timeout_s = 9;
+ FLAGS_otel_debug = true;
+ FLAGS_otel_trace_retry_policy_max_attempts = 8;
+ FLAGS_otel_trace_retry_policy_initial_backoff_s = 7.0;
+ FLAGS_otel_trace_retry_policy_max_backoff_s = 6;
+ FLAGS_otel_trace_retry_policy_backoff_multiplier = 42.0;
+ FLAGS_otel_trace_ssl_ciphers = "override_ssl_ciphers";
+ FLAGS_otel_trace_tls_cipher_suites = "override_tls_ciphers";
+ FLAGS_otel_trace_tls_insecure_skip_verify = true;
+ FLAGS_otel_trace_ca_cert_path = "ca_cert_path";
+ FLAGS_otel_trace_ca_cert_string = "ca_cert_string";
+ FLAGS_otel_trace_compression = false;
+
+ OtlpHttpExporterOptions actual = test::get_http_exporter_config();
+
+ EXPECT_EQ("https://foo.com", actual.url);
+ EXPECT_EQ(true, actual.console_debug);
+ EXPECT_EQ(chrono::seconds(9), actual.timeout);
+ EXPECT_EQ(8, actual.retry_policy_max_attempts);
+ EXPECT_EQ(chrono::seconds(7), actual.retry_policy_initial_backoff);
+ EXPECT_EQ(chrono::seconds(6), actual.retry_policy_max_backoff);
+ EXPECT_EQ(42.0, actual.retry_policy_backoff_multiplier);
+ EXPECT_EQ("1.3", actual.ssl_min_tls);
+ EXPECT_EQ("override_ssl_ciphers", actual.ssl_cipher);
+ EXPECT_EQ("override_tls_ciphers", actual.ssl_cipher_suite);
+ EXPECT_EQ(true, actual.ssl_insecure_skip_verify);
+ EXPECT_EQ("ca_cert_path", actual.ssl_ca_cert_path);
+ EXPECT_EQ("ca_cert_string", actual.ssl_ca_cert_string);
+ EXPECT_EQ("none", actual.compression);
+ EXPECT_TRUE(actual.http_headers.empty());
+}
+
+// The otel_trace_additional_headers flag allows for specifying arbitrary HTTP
headers
+// that are added to each HTTP request to the OTel collector. Assert one
additional header
+// is correctly parsed.
+TEST(OtelTest, InitOneHttpHeader) {
+ FLAGS_otel_trace_additional_headers = "foo=bar";
+ OtlpHttpExporterOptions actual = test::get_http_exporter_config();
+
+ EXPECT_EQ(1, actual.http_headers.size());
+ const auto val = actual.http_headers.find("foo");
+ ASSERT_NE(actual.http_headers.cend(), val) << "Could not find header with
key 'foo'";
+ EXPECT_EQ("bar", val->second);
+}
+
+// The otel_trace_additional_headers flag allows for specifying arbitrary HTTP
headers
+// that are added to each HTTP request to the OTel collector. Assert multiple
additional
+// headers (including the same header specified twice) are correctly parsed.
+TEST(OtelTest, InitMultipleHttpHeaders) {
+ FLAGS_otel_trace_additional_headers =
"foo=bar1:::foo2=bar3:::foo=bar2:::foo3=bar4";
+ OtlpHttpExporterOptions actual = test::get_http_exporter_config();
+
+ EXPECT_EQ(4, actual.http_headers.size());
+
+ const auto val2 = actual.http_headers.find("foo2");
+ ASSERT_NE(actual.http_headers.cend(), val2) << "Could not find header with
key 'foo2'";
+ EXPECT_EQ("bar3", val2->second);
+
+ const auto val3 = actual.http_headers.find("foo3");
+ ASSERT_NE(actual.http_headers.cend(), val3) << "Could not find header with
key 'foo3'";
+ EXPECT_EQ("bar4", val3->second);
+
+ bool val1_found = false;
+ bool val2_found = false;
+
+ for (auto iter : actual.http_headers) {
+ if (iter.first == "foo") {
+ if (iter.second == "bar1") {
+ val1_found = true;
+ } else if (iter.second == "bar2") {
+ val2_found = true;
+ }
+ }
+ }
+
+ EXPECT_TRUE(val1_found) << "Did not find header with key 'foo' and value
'bar1'";
+ EXPECT_TRUE(val2_found) << "Did not find header with key 'foo' and value
'bar2'";
+}
+
+// Assert the default values of the BatchSpanProcessorOptions struct used to
configure
+// the BatchSpanProcessor.
+TEST(OtelTest, BatchSpanProcessorDefaults) {
+ const BatchSpanProcessorOptions actual = test::get_batch_processor_config();
+
+ // Defaults come from the BatchSpanProcessorOptions struct definition.
+ EXPECT_EQ(512, actual.max_export_batch_size);
+ EXPECT_EQ(2048, actual.max_queue_size);
+ EXPECT_EQ(chrono::milliseconds(5000), actual.schedule_delay_millis);
+}
+
+// Assert the flags that customize the values of the BatchSpanProcessorOptions
struct
+// used to configure the BatchSpanProcessor.
+TEST(OtelTest, BatchSpanProcessorOverrides) {
+ FLAGS_otel_trace_batch_max_batch_size = 1;
+ FLAGS_otel_trace_batch_queue_size = 2;
+ FLAGS_otel_trace_batch_schedule_delay_ms = 3;
+
+ const BatchSpanProcessorOptions actual = test::get_batch_processor_config();
+
+ // Defaults come from the BatchSpanProcessorOptions struct definition.
+ EXPECT_EQ(1, actual.max_export_batch_size);
+ EXPECT_EQ(2, actual.max_queue_size);
+ EXPECT_EQ(chrono::milliseconds(3), actual.schedule_delay_millis);
+}
+
+// Assert an OtlpHttpExporter is created based on the default value of the
+// otel_trace_exporter flag and assert the default value of that flag.
+TEST(OtelTest, InitExporterHttp) {
+ EXPECT_EQ("otlp_http", FLAGS_otel_trace_exporter);
+ unique_ptr<SpanExporter> exporter = test::get_exporter();
+
+ ASSERT_NE(nullptr, exporter);
+ EXPECT_NE(nullptr, dynamic_cast<OtlpHttpExporter*>(exporter.get()));
+}
+
+// Assert an OtlpFileExporter is created when the otel_trace_exporter flag is
set to
+// "file".
+TEST(OtelTest, InitExporterFile) {
+ FLAGS_otel_trace_exporter = "file";
+ unique_ptr<SpanExporter> exporter = test::get_exporter();
+
+ ASSERT_NE(nullptr, exporter);
+ EXPECT_NE(nullptr, dynamic_cast<OtlpFileExporter*>(exporter.get()));
+}
+
+// Assert a BatchSpanProcessor is created based on the default value of the
+// otel_trace_span_processor flag and assert the default value of that flag.
+TEST(OtelTest, InitSpanProcessorBatch) {
+ EXPECT_EQ("batch", FLAGS_otel_trace_span_processor);
+ unique_ptr<SpanProcessor> processor = test::get_span_processor();
+
+ ASSERT_NE(nullptr, processor);
+ EXPECT_NE(nullptr, dynamic_cast<BatchSpanProcessor*>(processor.get()));
+}
+
+// Assert a SimpleSpanProcessor is created when the otel_trace_span_processor
flag is set
+// to "simple".
+TEST(OtelTest, InitSpanProcessorSimple) {
+ FLAGS_otel_trace_span_processor = "simple";
+ unique_ptr<SpanProcessor> processor = test::get_span_processor();
+
+ ASSERT_NE(nullptr, processor);
+ EXPECT_NE(nullptr, dynamic_cast<SimpleSpanProcessor*>(processor.get()));
+}
+
+// Assert that when otel_debug is true, the GlobalLogHandler is set to an
OtelLogHandler
+// instance and the OTel global log level is set to Debug.
+// Asserts the OTel global log handler is correctly initialized.
+TEST(OtelTest, InitLogHandlerDebug) {
+ FLAGS_otel_debug = true;
+ init_otel_tracer();
+
+ ASSERT_NE(nullptr, GlobalLogHandler::GetLogHandler().get());
+ EXPECT_NE(nullptr, dynamic_cast<OtelLogHandler*>(
+ GlobalLogHandler::GetLogHandler().get()));
+ EXPECT_EQ(LogLevel::Debug, GlobalLogHandler::GetLogLevel());
+
+ shutdown_otel_tracer();
+}
+
+// Assert that when otel_debug is false but VLOG(1) is enabled, the OTel
global log level
+// is set to Info.
+TEST(OtelTest, InitLogHandlerInfoV1) {
+ FLAGS_otel_debug = false;
+ auto vlog_setter = ScopedFlagSetter<int32_t>::Make(&FLAGS_v, 1);
+ init_otel_tracer();
+
+ EXPECT_EQ(LogLevel::Info, GlobalLogHandler::GetLogLevel());
+
+ shutdown_otel_tracer();
+}
+
+// Assert that when otel_debug is false but VLOG(2) is enabled, the OTel
global log level
+// is set to Info.
+TEST(OtelTest, InitLogHandlerInfoV2) {
+ FLAGS_otel_debug = false;
+ auto vlog_setter = ScopedFlagSetter<int32_t>::Make(&FLAGS_v, 2);
+ init_otel_tracer();
+
+ EXPECT_EQ(LogLevel::Info, GlobalLogHandler::GetLogLevel());
+
+ shutdown_otel_tracer();
+}
+
+// Assert that when otel_debug is false and VLOG(1) is disabled, the OTel
global log level
+// is set to None.
+TEST(OtelTest, InitLogHandlerNone) {
+ FLAGS_otel_debug = false;
+ auto vlog_setter = ScopedFlagSetter<int32_t>::Make(&FLAGS_v, 0);
+ init_otel_tracer();
+
+ EXPECT_EQ(LogLevel::None, GlobalLogHandler::GetLogLevel());
+
+ shutdown_otel_tracer();
+}
diff --git a/be/src/observe/otel.cc b/be/src/observe/otel.cc
index b46224110..e10d4afae 100644
--- a/be/src/observe/otel.cc
+++ b/be/src/observe/otel.cc
@@ -56,7 +56,6 @@
#include <opentelemetry/version.h>
#include "common/compiler-util.h"
-#include "common/status.h"
#include "common/version.h"
#include "gen-cpp/Query_types.h"
#include "observe/otel-log-handler.h"
@@ -75,7 +74,6 @@ DECLARE_string(otel_trace_additional_headers);
DECLARE_int32(otel_trace_batch_queue_size);
DECLARE_int32(otel_trace_batch_max_batch_size);
DECLARE_int32(otel_trace_batch_schedule_delay_ms);
-DECLARE_bool(otel_trace_beeswax);
DECLARE_string(otel_trace_ca_cert_path);
DECLARE_string(otel_trace_ca_cert_string);
DECLARE_string(otel_trace_collector_url);
@@ -144,7 +142,7 @@ static inline bool otel_tls_enabled() {
bool should_otel_trace_query(std::string_view sql,
const TSessionType::type& session_type) {
- if (LIKELY(!FLAGS_otel_trace_beeswax) && session_type ==
TSessionType::BEESWAX) {
+ if (UNLIKELY(session_type == TSessionType::BEESWAX)) {
return false;
}
@@ -198,12 +196,9 @@ bool should_otel_trace_query(std::string_view sql,
return false;
} // function should_otel_trace_query
-// Initializes an OtlpHttpExporter instance with configuration from global
flags. The
-// OtlpHttpExporter instance implements the SpanExporter interface. The
function parameter
-// `exporter` is an in-out parameter that will be populated with the created
-// OtlpHttpExporter instance. Returns Status::OK() on success, or an error
Status if
-// configuration fails.
-static Status init_exporter_http(unique_ptr<SpanExporter>& exporter) {
+// Creates an OtlpHttpExporterOptions struct instance with configuration from
global
+// startup flags.
+static OtlpHttpExporterOptions http_exporter_config() {
// Configure OTLP HTTP exporter
OtlpHttpExporterOptions opts;
opts.url = FLAGS_otel_trace_collector_url;
@@ -228,15 +223,20 @@ static Status
init_exporter_http(unique_ptr<SpanExporter>& exporter) {
// TLS Configurations
if (otel_tls_enabled()) {
+ // Set minimum TLS version to the value of the global ssl_minimum_version
flag.
+ // Since this flag is in the format "tlv1.2" or "tlsv1.3", we need to
+ // convert it to the format expected by OtlpHttpExporterOptions by
removing the
+ // "tlsv" prefix.
if (FLAGS_otel_trace_tls_minimum_version.empty()) {
- // Set minimum TLS version to the value of the global
ssl_minimum_version flag.
- // Since this flag is in the format "tlv1.2" or "tlsv1.3", we need to
- // convert it to the format expected by OtlpHttpExporterOptions.
if (!FLAGS_ssl_minimum_version.empty()) {
- opts.ssl_min_tls = FLAGS_ssl_minimum_version.substr(4); // Remove
"tlsv" prefix
+ opts.ssl_min_tls = FLAGS_ssl_minimum_version.substr(4);
+ } else {
+ LOG(WARNING) << "TLS is enabled for the OTel exporter, but neither the
"
+ "'ssl_minimum_version' nor the 'otel_trace_tls_minimum_version'
flags are "
+ "set.";
}
} else {
- opts.ssl_min_tls = FLAGS_otel_trace_tls_minimum_version;
+ opts.ssl_min_tls = FLAGS_otel_trace_tls_minimum_version.substr(4);
}
opts.ssl_insecure_skip_verify = FLAGS_otel_trace_tls_insecure_skip_verify;
@@ -247,6 +247,10 @@ static Status init_exporter_http(unique_ptr<SpanExporter>&
exporter) {
FLAGS_otel_trace_ssl_ciphers;
opts.ssl_cipher_suite = FLAGS_otel_trace_tls_cipher_suites.empty() ?
FLAGS_tls_ciphersuites : FLAGS_otel_trace_tls_cipher_suites;
+
+ VLOG(2) << "OTel minimum TLS version set to '" << opts.ssl_min_tls << "'";
+ VLOG(2) << "OTel TLS 1.2 allowed ciphers set to '" << opts.ssl_cipher <<
"'";
+ VLOG(2) << "OTel TLS 1.3 allowed ciphers set to '" <<
opts.ssl_cipher_suite << "'";
}
// Additional HTTP headers
@@ -261,10 +265,21 @@ static Status
init_exporter_http(unique_ptr<SpanExporter>& exporter) {
}
}
- exporter = OtlpHttpExporterFactory::Create(opts);
+ return opts;
+} // function http_exporter_config
+
+// Creates a BatchSpanProcessorOptions struct instance with configuration from
global
+// startup flags.
+static BatchSpanProcessorOptions batch_processor_config() {
+ BatchSpanProcessorOptions batch_opts;
- return Status::OK();
-} // function init_exporter_http
+ batch_opts.max_queue_size = FLAGS_otel_trace_batch_queue_size;
+ batch_opts.max_export_batch_size = FLAGS_otel_trace_batch_max_batch_size;
+ batch_opts.schedule_delay_millis =
+ chrono::milliseconds(FLAGS_otel_trace_batch_schedule_delay_ms);
+
+ return batch_opts;
+} // function batch_processor_config
// Initializes an OtlpFileExporter instance with configuration from global
flags. The
// OtlpFileExporter instance implements the SpanExporter interface. Returns a
unique_ptr
@@ -289,51 +304,31 @@ static unique_ptr<SpanExporter> init_exporter_file() {
return OtlpFileExporterFactory::Create(exporter_opts);
} // function init_exporter_file
-// Initializes the OpenTelemetry Tracer singleton with the configuration
defined in the
-// coordinator startup flags. Returns Status::OK() on success, or an error
Status if
-// configuration fails.
-Status init_otel_tracer() {
- LOG(INFO) << "Initializing OpenTelemetry tracing.";
- VLOG(2) << "OpenTelemetry version: " << OPENTELEMETRY_VERSION;
- VLOG(2) << "OpenTelemetry ABI version: " << OPENTELEMETRY_ABI_VERSION;
- VLOG(2) << "OpenTelemetry namespace: "
- << OPENTELEMETRY_STRINGIFY(OPENTELEMETRY_NAMESPACE);
-
- otel_log_handler_ = nostd::shared_ptr<LogHandler>(new OtelLogHandler());
- GlobalLogHandler::SetLogHandler(otel_log_handler_);
-
- // Set the OpenTelemetry SDK internal log level based on the current glog
level. The SDK
- // does not support changing the log level once a Provider has been created.
- if (FLAGS_otel_debug) {
- GlobalLogHandler::SetLogLevel(LogLevel::Debug);
- } else if (VLOG_IS_ON(1)) {
- GlobalLogHandler::SetLogLevel(LogLevel::Info);
- } else {
- GlobalLogHandler::SetLogLevel(LogLevel::None);
- }
-
+// Initializes a SpanExporter instance based on the FLAGS_otel_trace_exporter
flag.
+// Returns a unique_ptr which will always be initialized with the created
exporter.
+static unique_ptr<SpanExporter> init_exporter() {
unique_ptr<SpanExporter> exporter;
if(FLAGS_otel_trace_exporter == OTEL_EXPORTER_OTLP_HTTP) {
- RETURN_IF_ERROR(init_exporter_http(exporter));
+ exporter = OtlpHttpExporterFactory::Create(http_exporter_config());
} else {
exporter = init_exporter_file();
}
VLOG(2) << "OpenTelemetry exporter: " << FLAGS_otel_trace_exporter;
- // Set up tracer provider
+ return exporter;
+} // function init_exporter
+
+// Initializes a SpanProcessor instance based on the
FLAGS_otel_trace_span_processor flag.
+// Returns a unique_ptr which will always be initialized with the created
processor.
+static unique_ptr<SpanProcessor> init_span_processor() {
+ unique_ptr<SpanExporter> exporter = init_exporter();
unique_ptr<SpanProcessor> processor;
if (boost::iequals(trim_copy(FLAGS_otel_trace_span_processor),
SPAN_PROCESSOR_BATCH)) {
VLOG(2) << "Using BatchSpanProcessor for OpenTelemetry spans";
- BatchSpanProcessorOptions batch_opts;
-
- batch_opts.max_queue_size = FLAGS_otel_trace_batch_queue_size;
- batch_opts.max_export_batch_size = FLAGS_otel_trace_batch_max_batch_size;
- batch_opts.schedule_delay_millis =
- chrono::milliseconds(FLAGS_otel_trace_batch_schedule_delay_ms);
-
- processor = BatchSpanProcessorFactory::Create(move(exporter), batch_opts);
+ processor = BatchSpanProcessorFactory::Create(move(exporter),
+ batch_processor_config());
} else {
VLOG(2) << "Using SimpleSpanProcessor for OTel spans";
LOG(WARNING) << "Setting --otel_trace_span_processor=simple blocks the
query "
@@ -342,13 +337,37 @@ Status init_otel_tracer() {
processor = make_unique<SimpleSpanProcessor>(move(exporter));
}
- provider_ = TracerProviderFactory::Create(move(processor),
+ return processor;
+} // function init_span_processor
+
+// Initializes the OpenTelemetry Tracer singleton with the configuration
defined in the
+// coordinator startup flags. This tracer is stored in a static variabled
defined in this
+// file.
+void init_otel_tracer() {
+ LOG(INFO) << "Initializing OpenTelemetry tracing.";
+ VLOG(2) << "OpenTelemetry version: " << OPENTELEMETRY_VERSION;
+ VLOG(2) << "OpenTelemetry ABI version: " << OPENTELEMETRY_ABI_VERSION;
+ VLOG(2) << "OpenTelemetry namespace: "
+ << OPENTELEMETRY_STRINGIFY(OPENTELEMETRY_NAMESPACE);
+
+ otel_log_handler_ = nostd::shared_ptr<LogHandler>(new OtelLogHandler());
+ GlobalLogHandler::SetLogHandler(otel_log_handler_);
+
+ // Set the OpenTelemetry SDK internal log level based on the current glog
level. The SDK
+ // does not support changing the log level once a Provider has been created.
+ if (FLAGS_otel_debug) {
+ GlobalLogHandler::SetLogLevel(LogLevel::Debug);
+ } else if (VLOG_IS_ON(1)) {
+ GlobalLogHandler::SetLogLevel(LogLevel::Info);
+ } else {
+ GlobalLogHandler::SetLogLevel(LogLevel::None);
+ }
+
+ provider_ = TracerProviderFactory::Create(init_span_processor(),
sdk::resource::Resource::Create({
{"service.name", "Impala"},
{"service.version", GetDaemonBuildVersion()}
}));
-
- return Status::OK();
} // function init_otel_tracer
void shutdown_otel_tracer() {
@@ -371,6 +390,23 @@ namespace test {
bool otel_tls_enabled_for_testing() {
return otel_tls_enabled();
}
+
+OtlpHttpExporterOptions get_http_exporter_config() {
+ return http_exporter_config();
+}
+
+BatchSpanProcessorOptions get_batch_processor_config() {
+ return batch_processor_config();
+}
+
+unique_ptr<SpanExporter> get_exporter() {
+ return init_exporter();
+}
+
+unique_ptr<SpanProcessor> get_span_processor() {
+ return init_span_processor();
+}
+
} // namespace test
} // namespace impala
\ No newline at end of file
diff --git a/be/src/observe/otel.h b/be/src/observe/otel.h
index b11ea7569..c87a8d6a7 100644
--- a/be/src/observe/otel.h
+++ b/be/src/observe/otel.h
@@ -21,7 +21,11 @@
#include <string>
#include <string_view>
-#include "common/status.h"
+#include <opentelemetry/exporters/otlp/otlp_http_exporter_options.h>
+#include <opentelemetry/sdk/trace/batch_span_processor_options.h>
+#include <opentelemetry/sdk/trace/exporter.h>
+#include <opentelemetry/sdk/trace/processor.h>
+
#include "gen-cpp/Query_types.h"
#include "observe/span-manager.h"
#include "service/client-request-state.h"
@@ -47,7 +51,7 @@ bool should_otel_trace_query(std::string_view sql,
// Initializes the OpenTelemetry tracer with the configuration defined in the
coordinator
// startup flags (see otel-flags.cc and otel-flags-trace.cc for the list).
Does not verify
// that OpenTelemetry tracing is enabled (otel_trace_enabled flag).
-Status init_otel_tracer();
+void init_otel_tracer();
// Force flushes any buffered spans and shuts down the OpenTelemetry tracer.
void shutdown_otel_tracer();
@@ -58,6 +62,20 @@ std::shared_ptr<SpanManager>
build_span_manager(ClientRequestState*);
namespace test {
// Testing helper function to provide access to the static otel_tls_enabled()
function.
bool otel_tls_enabled_for_testing();
+
+// Testing helper function to provide access to the static
http_exporter_config()
+// function.
+opentelemetry::exporter::otlp::OtlpHttpExporterOptions
get_http_exporter_config();
+
+// Testing helper function to provide access to the static
batch_processor_config()
+// function.
+opentelemetry::sdk::trace::BatchSpanProcessorOptions
get_batch_processor_config();
+
+// Testing helper function to provide access to the static init_exporter()
function.
+std::unique_ptr<opentelemetry::sdk::trace::SpanExporter> get_exporter();
+
+// Testing helper function to provide access to the static
init_span_processor() function.
+std::unique_ptr<opentelemetry::sdk::trace::SpanProcessor> get_span_processor();
} // namespace test
} // namespace impala
diff --git a/be/src/runtime/exec-env.cc b/be/src/runtime/exec-env.cc
index 8370db0f3..6dc9d1bd6 100644
--- a/be/src/runtime/exec-env.cc
+++ b/be/src/runtime/exec-env.cc
@@ -349,7 +349,7 @@ Status ExecEnv::Init() {
// Initialize OTel
if (FLAGS_is_coordinator && FLAGS_otel_trace_enabled) {
- RETURN_IF_ERROR(init_otel_tracer());
+ init_otel_tracer();
}
// Initialize thread pools
diff --git a/be/src/testutil/localhost.key b/be/src/testutil/localhost.key
new file mode 100644
index 000000000..287885f53
--- /dev/null
+++ b/be/src/testutil/localhost.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAsdJ1cqffI9xssQysLHF4IiAzE9YSY1Ug3soiPPsJ6q32oWCS
+gHcV+u5/aV9v0PD2I4LGlm8rOtSiObCO6CNWrExB2Pznd02RwvJi90BCo8EcTH44
+676+69WiFCtrdQbwDJP8XRZLWNrkOPUTAuMOdGuQkKtjGoOTssJmVZzxv+UcJW2B
+Och0hCbivajB+e0qoTrTx1hPRmW/9sTVJNDIVPt0gMoc6EYndOz+4BNqhySBu2dG
+fBcaQ2PwCPh8Zgnztubw8iwBPIs1oNY3n3djWPnxo8ZG82nFqu9L435iy7/hGBZG
+DRUUgUizNdS8xCt0uL7TXOH/gllyF2hxVH+jxQIDAQABAoIBAHMwJp53+gbL4aiq
+0dkUQ8KvYwbldBHeciV/gMBJyfm4aPvOh/gprBZZajWC+fa6MGd+bk/CgZlhZhjC
+sz/SrHF+EGWUJghVOiezRcJuYPycuk0espabgCdawtwX6ErtjJBJSH+wUmyjlpUC
+xCbpmFJ33zSnoNHrC8EPRqUMvlkT5xaH3wWY6MmqKvurhmeVM6csYJy2LFnLuAcv
+Kyt0yNVsj4TYeABYfQRycLwiHE5oGhKgMva8M4qN98xtkZ9JnpLVlbC4Xy5xX4Hf
+2m4b0DR0QlmxxaahdxDvVyorSPE3oI9bZHot5Xjglq2hgg3pMMc5mxY5kFFpB6+9
+7AXP4kECgYEA3TfH+sSCLAocsKWioB0j6mG5kEB6oUW1pTC16LezEgM9O5H7Agqe
+SKQHHRgkyjkz7wiN5ByEP4srPDcEgEjSKeh01DyFCK1IrQA+mxLN3m//vDWCLHrb
+UiZSEXiw79jv8xqoCxMKj25UV/NTYp7LuNZOhsP10AOMmY3aGNBfKJECgYEAzcf1
+RXGXK3xwq0DpYshsrhLksm8GGYiKtNPle1y+jc0YK07k7d0UdcIfCPrXChhaWhUu
+lNWdIM9hYtN+nNyrUluG/dbS8A1Xiw/gmvCLf7wLJ52mjOKuY5V1yLiEWzd04Ysx
+3nz14Wv+/YsMJSNVky2dZa2PXxkM8LOjGmaRQfUCgYBXRc1oWiQ8uZSOABqDbluf
++QPbLAT1IOpDjE8Hy4ki3xJGMRZEvOmrIMMJsF+7RAwADnDkAHgQFZht/gqRjakU
+DXghzupw/OQCFGmehjGfwrGyj62WXLWv2BxidinfxccMMoT/MXjmExHFTOKlsp4O
+gsWiFycf9HaAkdzsEzCncQKBgQCjByTA5JIgKJFWi7GayjCX5G39E0pg1jUVt75Z
+8osg6niYbwOdkwYPmUBfK+NLoymJrrhdv7KheMqtseLgQU8Vi1+yIQyyk89kY6rM
+9X9/LiokM5jsivYf/Rv4bn6liZT2zwEuRA/EjHvSwONZVNoKJRxKnqs0azM+SwMP
++mxgNQKBgFpvqbAQyQFOWqngu2gMRV+D/K4VkY5mUGliwy9TOtUUAZ8YrmxI0vN8
+CP4WaV6iDvrXvomFRN94ycOxiSNRanQ5ItBava6PHo6YnFCdREaUDnTx3Jp1IGnk
+SZtV1P2LHzHlCtH0pZwhhOauveS7GPTBQDXZMJ3ufKfdBViNy738
+-----END RSA PRIVATE KEY-----
diff --git a/be/src/testutil/localhost.pem b/be/src/testutil/localhost.pem
new file mode 100644
index 000000000..223a994c1
--- /dev/null
+++ b/be/src/testutil/localhost.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDTjCCAjagAwIBAgIUB8U8sXAUFbgKk2FmztEoZkC6JFswDQYJKoZIhvcNAQEL
+BQAwgYsxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxETAP
+BgNVBAoMCENsb3VkZXJhMQ8wDQYDVQQLDAZJbXBhbGExGTAXBgNVBAMMEFdpbGRj
+YXJkIFJvb3QgQ0ExIzAhBgkqhkiG9w0BCQEWFHNhaWxlc2hAY2xvdWRlcmEuY29t
+MCAXDTI1MTAxMzE0MTQ0MloYDzIxMjUwOTE5MTQxNDQyWjAUMRIwEAYDVQQDDAls
+b2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx0nVyp98j
+3GyxDKwscXgiIDMT1hJjVSDeyiI8+wnqrfahYJKAdxX67n9pX2/Q8PYjgsaWbys6
+1KI5sI7oI1asTEHY/Od3TZHC8mL3QEKjwRxMfjjrvr7r1aIUK2t1BvAMk/xdFktY
+2uQ49RMC4w50a5CQq2Mag5OywmZVnPG/5RwlbYE5yHSEJuK9qMH57SqhOtPHWE9G
+Zb/2xNUk0MhU+3SAyhzoRid07P7gE2qHJIG7Z0Z8FxpDY/AI+HxmCfO25vDyLAE8
+izWg1jefd2NY+fGjxkbzacWq70vjfmLLv+EYFkYNFRSBSLM11LzEK3S4vtNc4f+C
+WXIXaHFUf6PFAgMBAAGjHjAcMBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATAN
+BgkqhkiG9w0BAQsFAAOCAQEAmW0tQjNXzysc0iViaRpjapNfgDLIVSgw18dzmBYK
+mMK1kFFxgdXcr2PmzXs7dnuUnO5UbvqXdIsAa0UqSZwQvSjFbwpMLdEJ9fj4H9aH
+N42BkL/oDomI5CS2hKCcY7yFtLZaNQHfJRDbzd9EzmmVURtGDyGwqKfT6ThbT9r+
+ec+jVtR1Lj5tnCh0++7eJfUJaMZ6FXp6vluGvkoSZPywvXp7H8FXqRvcXrBRrvrb
+CoOVqrahmifyBRRL/uOBkakLxd/dbcArlo1I3P40LG7SHJ/QUwiflPVz2pApdMt+
+9HTvP6uRU0PdqxzoEvJ+mZA+ygePUdUF7xu9oM8OfxJXIQ==
+-----END CERTIFICATE-----
diff --git a/testdata/bin/otel-collector/README.md
b/testdata/bin/otel-collector/README.md
index b52c818c8..1733fbfa7 100644
--- a/testdata/bin/otel-collector/README.md
+++ b/testdata/bin/otel-collector/README.md
@@ -6,7 +6,8 @@ This directory contains configuration to run an [OpenTelemetry
Collector](https:
## Contents
-- [`otel-config.yml`](./otel-config.yml): OpenTelemetry Collector
configuration file.
+- [`otel-config-http.yml`](./otel-config-http.yml): OpenTelemetry Collector
configuration file with the OTLP receiver supporting http.
+- [`otel-config-https.yml`](./otel-config-https.yml): OpenTelemetry Collector
configuration file with the OTLP receiver supporting https.
- [`docker-compose.yml`](./docker-compose.yml): Alternative Docker Compose
setup for both services.
---
@@ -16,7 +17,11 @@ This directory contains configuration to run an
[OpenTelemetry Collector](https:
### Option 1: Run Interactively
```bash
+ # HTTP (default)
docker-compose -f testdata/bin/otel-collector/docker-compose.yml up
+
+ # HTTPS
+ PROTOCOL=https docker-compose -f
testdata/bin/otel-collector/docker-compose.yml up
```
- This command:
@@ -28,7 +33,11 @@ This directory contains configuration to run an
[OpenTelemetry Collector](https:
### Option 2: Run Detached
```bash
+ # HTTP (default)
docker-compose -f testdata/bin/otel-collector/docker-compose.yml up -d
+
+ # HTTP (default)
+ PROTOCOL=https docker-compose -f
testdata/bin/otel-collector/docker-compose.yml up -d
```
- This command:
@@ -61,7 +70,8 @@ The collector forwards all received traces to Jaeger using
OTLP/gRPC.
To send traces from an Impala cluster to this collector, start Impala with the
following arguments:
```bash
-./bin/start-impala-cluster.py \
+# HTTP (default)
+start-impala-cluster.py \
--cluster_size=2 \
--num_coordinators=1 \
--use_exclusive_coordinators \
@@ -69,6 +79,17 @@ To send traces from an Impala cluster to this collector,
start Impala with the f
--otel_trace_collector_url=http://localhost:55888/v1/traces
--otel_trace_span_processor=simple \
--cluster_id=local_cluster"
+
+# HTTPS
+start-impala-cluster.py \
+ --cluster_size=2 \
+ --num_coordinators=1 \
+ --use_exclusive_coordinators \
+ --impalad_args="-v=2 --otel_trace_enabled=true \
+ --otel_trace_collector_url=https://localhost:55888/v1/traces \
+ --otel_trace_ca_cert_path=${IMPALA_HOME}/be/src/testutil/wildcardCA.pem \
+ --otel_trace_span_processor=simple \
+ --cluster_id=local_cluster"
```
- Ensure the collector is running before starting Impala.
diff --git a/testdata/bin/otel-collector/docker-compose.yml
b/testdata/bin/otel-collector/docker-compose.yml
index d2ab69961..7ebd4cc66 100644
--- a/testdata/bin/otel-collector/docker-compose.yml
+++ b/testdata/bin/otel-collector/docker-compose.yml
@@ -37,7 +37,9 @@ services:
depends_on:
- jaeger
volumes:
- - ./otel-config.yml:/etc/otel/config.yml
+ - ./otel-config-${PROTOCOL:-http}.yml:/etc/otel/config.yml:ro
+ - ../../../be/src/testutil/localhost.pem:/etc/otel/localhost.pem:ro
+ - ../../../be/src/testutil/localhost.key:/etc/otel/localhost.key:ro
command: ["--config", "/etc/otel/config.yml"]
ports:
- "55888:55888" # Expose OTLP HTTP externally
diff --git a/testdata/bin/otel-collector/otel-config.yml
b/testdata/bin/otel-collector/otel-config-http.yml
similarity index 100%
copy from testdata/bin/otel-collector/otel-config.yml
copy to testdata/bin/otel-collector/otel-config-http.yml
diff --git a/testdata/bin/otel-collector/otel-config.yml
b/testdata/bin/otel-collector/otel-config-https.yml
similarity index 90%
rename from testdata/bin/otel-collector/otel-config.yml
rename to testdata/bin/otel-collector/otel-config-https.yml
index f15c35172..c4fb22c77 100644
--- a/testdata/bin/otel-collector/otel-config.yml
+++ b/testdata/bin/otel-collector/otel-config-https.yml
@@ -22,6 +22,9 @@ receivers:
protocols:
http:
endpoint: 0.0.0.0:55888
+ tls:
+ cert_file: /etc/otel/localhost.pem
+ key_file: /etc/otel/localhost.key
exporters:
otlp:
@@ -33,4 +36,4 @@ service:
pipelines:
traces:
receivers: [otlp]
- exporters: [otlp]
+ exporters: [otlp]
\ No newline at end of file