After you use OpenTelemetry to instrument an application and report the trace data to Managed Service for OpenTelemetry, Managed Service for OpenTelemetry starts to monitor the application. You can view the monitoring data of the application such as application topology, trace, abnormal transactions, slow transactions, and SQL analysis. This topic describes how to use OpenTelemetry SDK for C++ to instrument a C++ application and report the trace data of the C++ application.
Prerequisites
Sample code
Download the sample code on the cpp-demo page.
Environment requirements
C++ 11 or later is installed.
You can obtain the supported C++ versions and development platforms on the opentelemetry-cpp page.
Step 1: Prepare the environment
Optional. Create a docker image in the C++ environment.
docker pull gcc # The image uses the Debian system. docker run -it --name otel-cpp-demo gcc bash
Install the following dependencies:
protobuf
grpc
apt-get update apt-get install sudo sudo apt-get install git cmake g++ libcurl4-openssl-dev # Install the protobuf dependency. sudo apt-get install protobuf-compiler libprotobuf-dev # Install the grpc dependency. sudo apt-get install -y libgrpc++-dev libgrpc-dev protobuf-compiler-grpc
Step 2: Install the 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
# Install the OpenTelemetry C++ library to the /usr/local path. We recommend that you install the OpenTelemetry C++ library to this path.
cmake --install .
# Install the OpenTelemetry C++ library to the specified path.
# cmake --install . --prefix /opentelemetry-cpp-lib
Step 3: Use the OpenTelemetry C++ library in a project
Report data over HTTP
Create a project.
mkdir otel-http-export-demo cd otel otel-http-export-demo
Write the CMakeLists.txt file in the project.
cmake_minimum_required(VERSION 3.25.1) # The version of CMake. project(otel-http-export-demo) # The project name. add_executable(otel-http-export-demo http_exporter.cc) # The project name and the main file. 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 )
Write a demo.
The sample code contains only one http_exporter.cc file.
Replace
${ServiceName}
with your application name and${HostName}
with your hostname.// 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() { // Create an OpenTelemetry Protocol (OTLP) exporter. auto exporter = otlp::OtlpHttpExporterFactory::Create(opts); auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter)); resource::ResourceAttributes attributes = { {resource::SemanticConventions::kServiceName, "${ServiceName}"}, // The application name. {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)); // Set the 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(); }
Compile the project.
mkdir build && cd build && cmake .. && make
Run the project.
./otel-http-export-demo ${http-endpoint}
Replace
${http-endpoint}
with the HTTP endpoint that is obtained in the Prerequisites section.Example:
./otel-http-export-demo http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxxx_xxxxx/api/otlp/traces
Report data over gRPC
Create a project.
mkdir otel-grpc-export-demo cd otel otel-grpc-export-demo
Write the CMakeLists.txt file in the project.
cmake_minimum_required(VERSION 3.25.1) # The version of CMake. project(otel-grpc-export-demo) # The project name. add_executable(otel-grpc-export-demo grpc_exporter.cc) # The project name and the main file. 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 )
Write a demo.
The test code contains only one grpc_exporter.cc file.
Replace
${ServiceName}
with your application name and${HostName}
with your hostname.// 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() { // Create an OTLP exporter. auto exporter = otlp::OtlpGrpcExporterFactory::Create(opts); auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter)); resource::ResourceAttributes attributes = { {resource::SemanticConventions::kServiceName, "${ServiceName} "}, // The application name. {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)); // Set the 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(); }
Compile the project.
mkdir build && cd build && cmake .. && make
Run the project.
./otel-grpc-export-demo ${gRPC-endpoint} ${token}
Replace
${gRPC-endpoint}
and${token}
with the gRPC endpoint and authentication token that are obtained in the Prerequisites section.Example:
./otel-grpc-export-demo http://tracing-analysis-dc-hz.aliyuncs.com:8090 xxxxx_xxxxxx
Common errors
The following error message may be returned after you run the demo:
./otel-grpc-export-demo: error while loading shared libraries: libopentelemetry_proto_grpc.so: cannot open shared object file: No such file or directory
Run the following command to modify the environment variable:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/
/usr/local/lib
indicates the path in which the opentelemetry-cpp demo is installed.
View the monitoring data
Log on to the ARMS console. In the left-side navigation pane, choose . On the Applications page, click the name of the application. On the page that appears, view the trace data.
If the icon is displayed in the Language column, the application is connected to Application Monitoring. If a hyphen (-) is displayed, the application is connected to Managed Service for OpenTelemetry.