通過(guò)OpenTelemetry上報(bào)C++應(yīng)用數(shù)據(jù)
通過(guò)OpenTelemetry為應(yīng)用埋點(diǎn)并上報(bào)鏈路數(shù)據(jù)至可觀測(cè)鏈路 OpenTelemetry 版后,可觀測(cè)鏈路 OpenTelemetry 版即可開(kāi)始監(jiān)控應(yīng)用,您可以查看應(yīng)用拓?fù)洹⒄{(diào)用鏈路、異常事務(wù)、慢事務(wù)和SQL分析等一系列監(jiān)控?cái)?shù)據(jù)。本文介紹如何使用OpenTelemetry為C++應(yīng)用埋點(diǎn)并上報(bào)數(shù)據(jù)。
前提條件
新版控制臺(tái)
登錄可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái),在左側(cè)導(dǎo)航欄單擊接入中心。
在開(kāi)源框架區(qū)域單擊OpenTelemetry卡片。
在彈出的OpenTelemetry面板中選擇數(shù)據(jù)需要上報(bào)的地域。
說(shuō)明初次接入的地域?qū)?huì)自動(dòng)進(jìn)行資源初始化。
選擇連接方式和上報(bào)方式,然后復(fù)制接入點(diǎn)信息。
連接方式:若您的服務(wù)部署在阿里云上,且所屬地域與選擇的接入地域一致,推薦使用阿里云內(nèi)網(wǎng)方式,否則選擇公網(wǎng)方式。
上報(bào)方式:根據(jù)客戶端支持的協(xié)議類型選擇HTTP或gRPC協(xié)議上報(bào)數(shù)據(jù)。
舊版控制臺(tái)
在左側(cè)導(dǎo)航欄單擊集群配置,然后在右側(cè)頁(yè)面單擊接入點(diǎn)信息頁(yè)簽。
在頁(yè)面頂部選擇需要接入的地域,然后在集群信息區(qū)域打開(kāi)顯示Token開(kāi)關(guān)。
在客戶端采集工具區(qū)域單擊OpenTelemetry。
在相關(guān)信息列中,獲取接入點(diǎn)信息。
說(shuō)明如果應(yīng)用部署于阿里云生產(chǎn)環(huán)境,則選擇阿里云VPC網(wǎng)絡(luò)接入點(diǎn),否則選擇公網(wǎng)接入點(diǎn)。
示例Demo
示例代碼倉(cāng)庫(kù)地址:opentelemetry-cpp-demo
環(huán)境要求
C++版本 ≥ 11
請(qǐng)?jiān)?a class="" >Supported C++ Versions and Development Platforms中查看支持的C++版本和開(kāi)發(fā)平臺(tái)。
步驟一:環(huán)境準(zhǔn)備
(可選)運(yùn)行C++鏡像。
docker pull gcc # 這個(gè)鏡像用的系統(tǒng)是debian docker run -it --name otel-cpp-demo gcc bash
安裝必備的依賴。
protobuf
grpc
apt-get update apt-get install sudo sudo apt-get install git cmake g++ libcurl4-openssl-dev # 安裝 protobuf sudo apt-get install protobuf-compiler libprotobuf-dev # 安裝 grpc sudo apt-get install -y libgrpc++-dev libgrpc-dev protobuf-compiler-grpc
步驟二:安裝OpenTelemetry C++ Library
git clone --recurse-submodules https://github.com/open-telemetry/opentelemetry-cpp
cd opentelemetry-cpp
mkdir build && cd build
cmake -DBUILD_TESTING=OFF -DWITH_OTLP_GRPC=ON -DWITH_OTLP_HTTP=ON ..
cmake --build . --target all
# 直接安裝到/usr/local(推薦)
cmake --install .
# 或者安裝到指定路徑
# cmake --install . --prefix /opentelemetry-cpp-lib
步驟三:在項(xiàng)目中使用OpenTelemetry C++ Library
通過(guò)HTTP上報(bào)數(shù)據(jù)
創(chuàng)建項(xiàng)目。
mkdir otel-http-export-demo cd otel otel-http-export-demo
編寫項(xiàng)目CMakeLists.txt文件。
cmake_minimum_required(VERSION 3.25.1) #version填cmake的版本,cmake --version project(otel-http-export-demo) # 括號(hào)里填項(xiàng)目名 add_executable(otel-http-export-demo http_exporter.cc) # 項(xiàng)目名和main文件 find_package(opentelemetry-cpp CONFIG REQUIRED) find_package(protobuf) find_package(gRPC) find_package(CURL) find_package(nlohmann_json) include_directories("${OPENTELEMETRY_CPP_INCLUDE_DIRS}") target_link_libraries( opentelemetry_trace opentelemetry_common opentelemetry_http_client_curl opentelemetry_exporter_otlp_http opentelemetry_exporter_otlp_grpc opentelemetry_exporter_otlp_http_client opentelemetry_otlp_recordable opentelemetry_resources )
編寫Demo。
測(cè)試代碼只包含一個(gè)http_exporter.cc文件。
請(qǐng)將
${ServiceName}
替換為您的應(yīng)用名,將${HostName}
替換為主機(jī)名。// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #include "opentelemetry/exporters/otlp/otlp_http_exporter_factory.h" #include "opentelemetry/exporters/otlp/otlp_http_exporter_options.h" #include "opentelemetry/context/propagation/global_propagator.h" #include "opentelemetry/context/propagation/text_map_propagator.h" #include "opentelemetry/exporters/ostream/span_exporter_factory.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/sdk/trace/simple_processor_factory.h" #include "opentelemetry/sdk/trace/tracer_context.h" #include "opentelemetry/sdk/trace/tracer_context_factory.h" #include "opentelemetry/sdk/trace/tracer_provider_factory.h" #include "opentelemetry/trace/propagation/http_trace_context.h" #include "opentelemetry/trace/provider.h" #include "opentelemetry/ext/http/client/http_client_factory.h" #include "opentelemetry/sdk/resource/semantic_conventions.h" #include "opentelemetry/sdk/common/global_log_handler.h" #include <string> namespace trace = opentelemetry::trace; namespace trace_sdk = opentelemetry::sdk::trace; namespace otlp = opentelemetry::exporter::otlp; namespace internal_log = opentelemetry::sdk::common::internal_log; namespace resource = opentelemetry::sdk::resource; namespace nostd = opentelemetry::nostd; namespace { opentelemetry::exporter::otlp::OtlpHttpExporterOptions opts; void InitTracer() { // 創(chuàng)建OTLP exporter auto exporter = otlp::OtlpHttpExporterFactory::Create(opts); auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter)); resource::ResourceAttributes attributes = { {resource::SemanticConventions::kServiceName, "${ServiceName}"}, // 應(yīng)用名 {resource::SemanticConventions::kHostName, "${HostName}"} }; auto resource = opentelemetry::sdk::resource::Resource::Create(attributes); std::shared_ptr<opentelemetry::trace::TracerProvider> provider = trace_sdk::TracerProviderFactory::Create(std::move(processor), std::move(resource)); // 設(shè)置Trace provider trace::Provider::SetTracerProvider(provider); } void CleanupTracer() { std::shared_ptr<opentelemetry::trace::TracerProvider> none; trace::Provider::SetTracerProvider(none); } nostd::shared_ptr<trace::Tracer> get_tracer() { auto provider = trace::Provider::GetTracerProvider(); return provider->GetTracer("library name to trace", OPENTELEMETRY_SDK_VERSION); } void f1() { auto scoped_span = trace::Scope(get_tracer()->StartSpan("f1")); } void f2() { auto scoped_span = trace::Scope(get_tracer()->StartSpan("f2")); f1(); f1(); } void foo_library() { auto scoped_span = trace::Scope(get_tracer()->StartSpan("library")); f2(); } } // namespace /* Usage: - example_otlp_http - example_otlp_http <URL> - example_otlp_http <URL> <DEBUG> - example_otlp_http <URL> <DEBUG> <BIN> <DEBUG> = yes|no, to turn console debug on or off <BIN> = bin, to export in binary format */ int main(int argc, char *argv[]) { if (argc > 1) { opts.url = argv[1]; if (argc > 2) { std::string debug = argv[2]; opts.console_debug = debug != "" && debug != "0" && debug != "no"; } if (argc > 3) { std::string binary_mode = argv[3]; if (binary_mode.size() >= 3 && binary_mode.substr(0, 3) == "bin") { opts.content_type = otlp::HttpRequestContentType::kBinary; } } } if (opts.console_debug) { internal_log::GlobalLogHandler::SetLogLevel(internal_log::LogLevel::Debug); } InitTracer(); foo_library(); CleanupTracer(); }
編譯項(xiàng)目。
mkdir build && cd build && cmake .. && make
運(yùn)行項(xiàng)目。
./otel-http-export-demo ${http-endpoint}
請(qǐng)將
${http-endpoint}
替換為前提條件中獲取的HTTP接入點(diǎn)信息。例如:
./otel-http-export-demo http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxxx_xxxxx/api/otlp/traces
通過(guò)gRPC上報(bào)數(shù)據(jù)
創(chuàng)建項(xiàng)目。
mkdir otel-grpc-export-demo cd otel otel-grpc-export-demo
編寫項(xiàng)目CMakeLists.txt文件。
cmake_minimum_required(VERSION 3.25.1) #version填cmake的版本,cmake --version project(otel-grpc-export-demo) # 括號(hào)里填項(xiàng)目名 add_executable(otel-grpc-export-demo grpc_exporter.cc) # 項(xiàng)目名和main文件 find_package(opentelemetry-cpp CONFIG REQUIRED) find_package(protobuf) find_package(gRPC) find_package(CURL) find_package(nlohmann_json) include_directories("${OPENTELEMETRY_CPP_INCLUDE_DIRS}") target_link_libraries( otel-grpc-export-demo ${OPENTELEMETRY_CPP_LIBRARIES} opentelemetry_trace opentelemetry_common opentelemetry_http_client_curl opentelemetry_exporter_otlp_http opentelemetry_exporter_otlp_grpc opentelemetry_exporter_otlp_http_client opentelemetry_otlp_recordable opentelemetry_resources )
編寫Demo。
測(cè)試代碼只包含一個(gè)grpc_exporter.cc文件。
請(qǐng)將
${ServiceName}
替換為您的應(yīng)用名,將${HostName}
替換為主機(jī)名。// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #include "opentelemetry/exporters/otlp/otlp_grpc_exporter_factory.h" #include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" #include "opentelemetry/context/propagation/global_propagator.h" #include "opentelemetry/context/propagation/text_map_propagator.h" #include "opentelemetry/exporters/ostream/span_exporter_factory.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/sdk/trace/simple_processor_factory.h" #include "opentelemetry/sdk/trace/tracer_context.h" #include "opentelemetry/sdk/trace/tracer_context_factory.h" #include "opentelemetry/sdk/trace/tracer_provider_factory.h" #include "opentelemetry/trace/propagation/http_trace_context.h" #include "opentelemetry/trace/provider.h" #include "opentelemetry/ext/http/client/http_client_factory.h" #include "opentelemetry/sdk/resource/semantic_conventions.h" #include "opentelemetry/sdk/common/global_log_handler.h" #include <string> namespace trace = opentelemetry::trace; namespace trace_sdk = opentelemetry::sdk::trace; namespace otlp = opentelemetry::exporter::otlp; namespace internal_log = opentelemetry::sdk::common::internal_log; namespace resource = opentelemetry::sdk::resource; namespace nostd = opentelemetry::nostd; namespace { opentelemetry::exporter::otlp::OtlpGrpcExporterOptions opts; void InitTracer() { // 創(chuàng)建OTLP exporter auto exporter = otlp::OtlpGrpcExporterFactory::Create(opts); auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter)); resource::ResourceAttributes attributes = { {resource::SemanticConventions::kServiceName, "${ServiceName} "}, // 應(yīng)用名 {resource::SemanticConventions::kHostName, "${HostName}"} }; auto resource = opentelemetry::sdk::resource::Resource::Create(attributes); std::shared_ptr<opentelemetry::trace::TracerProvider> provider = trace_sdk::TracerProviderFactory::Create(std::move(processor), std::move(resource)); // 設(shè)置Trace provider trace::Provider::SetTracerProvider(provider); } void CleanupTracer() { std::shared_ptr<opentelemetry::trace::TracerProvider> none; trace::Provider::SetTracerProvider(none); } nostd::shared_ptr<trace::Tracer> get_tracer() { auto provider = trace::Provider::GetTracerProvider(); return provider->GetTracer("library name to trace", OPENTELEMETRY_SDK_VERSION); } void f1() { auto scoped_span = trace::Scope(get_tracer()->StartSpan("f1")); } void f2() { auto scoped_span = trace::Scope(get_tracer()->StartSpan("f2")); f1(); f1(); } void foo_library() { auto scoped_span = trace::Scope(get_tracer()->StartSpan("library")); f2(); } } // namespace /* Usage: - example_otlp_grpc - example_otlp_grpc <URL> <TOKEN> */ int main(int argc, char *argv[]) { if (argc > 1) { opts.endpoint = argv[1]; if (argc > 2) { opts.metadata.insert(std::pair<std::string, std::string>("authentication",argv[2])); } if (argc > 3) { opts.use_ssl_credentials = true; opts.ssl_credentials_cacert_path = argv[3]; } } InitTracer(); foo_library(); CleanupTracer(); }
編譯項(xiàng)目。
mkdir build && cd build && cmake .. && make
運(yùn)行項(xiàng)目。
./otel-grpc-export-demo ${gRPC-endpoint} ${token}
請(qǐng)將
${gRPC-endpoint}
和${token}
替換為前提條件中獲取的gRPC接入點(diǎn)和鑒權(quán)Token。例如:
./otel-grpc-export-demo http://tracing-analysis-dc-hz.aliyuncs.com:8090 xxxxx_xxxxxx
常見(jiàn)報(bào)錯(cuò)
運(yùn)行后提示:
./otel-grpc-export-demo: error while loading shared libraries: libopentelemetry_proto_grpc.so: cannot open shared object file: No such file or directory
執(zhí)行以下命令修改環(huán)境變量。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/
/usr/local/lib
是opentelemetry-cpp安裝的地址。
查看監(jiān)控?cái)?shù)據(jù)
在可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái)的應(yīng)用列表頁(yè)面選擇目標(biāo)應(yīng)用,查看鏈路數(shù)據(jù)。