This topic describes how to import trace data from C++ applications to Simple Log Service by using OpenTelemetry SDK for C++.
Prerequisites
A trace instance is created. For more information, see Create a trace instance.
A development environment in which OpenTelemetry SDK for C++ can be compiled and run is prepared.
If you use CMake, make sure that the CMake version is 3.1 or later.
If you use GCC or G++, make sure that the GCC or G++ version is 4.8 or later.
If you use MSVC, make sure that the MSVC version is VS2015 or later. We recommend that you use VS2019.
The following C++ versions are supported:
ISO/IEC 14882:2011 (C++11, C++0x)
ISO/IEC 14882:2014 (C++14, C++1y)
ISO/IEC 14882:2017 (C++17, C++1z)
ISO/IEC 14882:2020 (C++20)
For more information about dependencies and versions, see opentelemetry-cpp.
Step 1: Integrate the SDK
You can use source code or a package manager to integrate the SDK. For more information, see Install opentelemetry-cpp.
Use source code to integrate the SDK and compile the SDK as an independent CMake project
Prerequisites
Compilation is supported in Windows, macOS, and Linux.
A C++ compiler that supports C++11 and later is installed.
Git is installed.
CMake is installed.
GoogleTest is installed.
Google Benchmark is installed.
Procedure
Obtain the opentelemetry-cpp source code.
$ cd <your-path> $ git clone --recurse-submodules https://github.com/open-telemetry/opentelemetry-cppCreate a CMake build configuration.
$ cd opentelemetry-cpp $ mkdir build && cd build && cmake ..Construct CMake targets.
$ cmake --build . --target allInstall API header files.
$ cmake --install . --prefix /<install-root>/
Use source code to integrate the SDK into a CMake project
Prerequisites
Compilation is supported in Windows, macOS, and Linux.
A C++ compiler that supports C++11 and later is installed.
Git is installed.
CMake is installed.
GoogleTest is installed.
Google Benchmark is installed.
Sample code
# CMakeLists.txt
find_package(opentelemetry-cpp CONFIG REQUIRED)
...
target_include_directories(foo PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS})
target_link_libraries(foo PRIVATE ${OPENTELEMETRY_CPP_LIBRARIES})Use a package manager to integrate the SDK
For more information about how to use package manager to integrate the SDK, see Using Package Managers.
Step 2: Initialize the SDK
You can use OpenTelemetry SDK for C++ only after you initialize the SDK. The following sample code provides an example on how to initialize the SDK:
// Import the following header files:
#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_factory.h"
#include "opentelemetry/sdk/trace/simple_processor_factory.h"
#include "opentelemetry/sdk/trace/tracer_provider_factory.h"
#include "opentelemetry/trace/provider.h"
#include "opentelemetry/sdk/trace/tracer_provider.h"
#include "opentelemetry/sdk/version/version.h"
#include "opentelemetry/trace/provider.h"
#include "opentelemetry/sdk/resource/resource.h"
#include "opentelemetry/sdk/resource/semantic_conventions.h"
namespace trace = opentelemetry::trace;
namespace trace_sdk = opentelemetry::sdk::trace;
namespace otlp = opentelemetry::exporter::otlp;
namespace resource = opentelemetry::sdk::resource;
namespace
{
// Initialize the exporter. The exporter is used to export trace data to a Simple Log Service Logstore.
opentelemetry::exporter::otlp::OtlpGrpcExporterOptions opts;
void InitTracer()
{
opts.endpoint = "https://${endpoint}";
opts.use_ssl_credentials = true;
opts.ssl_credentials_cacert_path = "<your root pem file path>"; // Specify the directory in which the root .pem file is stored. In most cases, the root .pem file is stored in the directory of the gRPC dependency library.
// Setup credentials info
opts.metadata.insert(std::pair<std::string, std::string>("x-sls-otel-project", "${project}"));
opts.metadata.insert(std::pair<std::string, std::string>("x-sls-otel-instance-id", "${instanceId}"));
opts.metadata.insert(std::pair<std::string, std::string>("x-sls-otel-ak-id", "${access-key-id}"));
opts.metadata.insert(std::pair<std::string, std::string>("x-sls-otel-ak-secret", "${access-key-secret}"));
// Create OTLP exporter instance
auto exporter = otlp::OtlpGrpcExporterFactory::Create(opts);
auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter));
// Initialize the tracer provider. The tracer provider is used to expose major API operations and preprocess spans.
// Configure the custom rules that are used to generate trace IDs and span IDs and configure custom samplers. You can configure the settings based on your business requirements.
resource::ResourceAttributes attributes = {
{resource::SemanticConventions::kServiceName, "${service}"}, // Generally, set the value to the name of the submodule.
{resource::SemanticConventions::kServiceNamespace, "${service.namespace}"}, // Generally, set the value to the name of the module or app.
{resource::SemanticConventions::kServiceVersion, "${version}"}, // Generally, set the value to the version number of the module or app.
{resource::SemanticConventions::kHostName, "${host}"},
{resource::SemanticConventions::kDeploymentEnvironment, "${environment}"}
};
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 global trace provider
trace::Provider::SetTracerProvider(provider);
}
void CleanupTracer()
{
// We call ForceFlush to prevent to cancel running exportings, It's optional.
opentelemetry::nostd::shared_ptr<opentelemetry::trace::TracerProvider> provider =
trace::Provider::GetTracerProvider();
if (provider)
{
static_cast<trace_sdk::TracerProvider*>(provider.get())->ForceFlush();
}
std::shared_ptr<opentelemetry::trace::TracerProvider> none;
trace::Provider::SetTracerProvider(none);
}
} // namespaceVariable | Description | Example |
| The endpoint of the Simple Log Service project. Format:
| test-project.cn-hangzhou.log.aliyuncs.com:10010 |
| The name of the Simple Log Service project. | test-project |
| The ID of the trace instance. For more information, see Create a trace instance. | test-traces |
| The AccessKey ID of your Alibaba Cloud account. Important We recommend that you use the AccessKey pair of a Resource Access Management (RAM) user that has only the write permissions on the Simple Log Service project. An AccessKey pair consists of an AccessKey ID and an AccessKey secret. For more information about how to grant the write permissions on a specified project to a RAM user, see Use custom policies to grant permissions to a RAM user. For more information about how to obtain an AccessKey pair, see AccessKey pair. | None |
| The AccessKey secret of your Alibaba Cloud account. Important We recommend that you use the AccessKey pair of a RAM user that has only the write permissions on the Simple Log Service project. | None |
| The namespace to which the service belongs. | order |
| The name of the service. Specify the value based on your business requirements. | payment |
| The version of the service. We recommend that you specify a version in the va.b.c format. | v0.1.2 |
| The hostname. | localhost |
| The deployment environment. Example: test environment or production environment. Specify the value based on your business requirements. | pre |
Step 3: Use the SDK
Create a tracer
We recommend that you create a tracer based on your business scenario. When you create a tracer, you must specify a library name. This way, you can distinguish trace data by library.
namespace trace = opentelemetry::trace;
namespace nostd = opentelemetry::nostd;
namespace
{
nostd::shared_ptr<trace::Tracer> get_tracer()
{
auto provider = trace::Provider::GetTracerProvider();
return provider->GetTracer("<your library name>", OPENTELEMETRY_SDK_VERSION);
}
} // namespaceCreate a basic span
A span specifies an operation in a transaction. Each span encapsulates the operation name, start timestamp and end timestamp, attributes, events, and context.
auto span = get_tracer()->StartSpan("basic_f1");
// do your stuff
// ...
span->End();Create a nested span
If you want to create a nested span to trace work in a nested operation, you can use OpenTelemetry to trace the operation threads in an on-premises process and across remote processes. In the following examples, method A calls method B. You can create a nested span based on the following examples:
void method_a()
{
auto span = get_tracer()->StartSpan("operation A");
auto scope = get_tracer()->WithActiveSpan(span);
method_b();
span->End();
}
void method_b()
{
auto span_child = get_tracer()->StartSpan("operation B");
// do your stuff
// ...
span_child->End();
}OpenTelemetry API provides an automated method to propagate a parent span.
void method_a()
{
auto scoped_span = trace::Scope(get_tracer()->StartSpan("operation A"));
method_b();
}
void method_b()
{
auto scoped_span = trace::Scope(get_tracer()->StartSpan("operation B"));
}Create a span annotated with attributes
You can provide context for a specific operation in a span by specifying attributes. For example, you can provide execution results and related business information.
auto span = get_tracer()->StartSpan("<my operation>");
span->SetAttribute("age", 12);
span->SetAttribute("sex", "man");
// do your stuff
// ...
span->SetAttribute("height", 154.5);
span->End();Create a span annotated with events
You can use multiple events to annotate a span.
auto span = get_tracer()->StartSpan("<my operation>");
// do your stuff
// ...
span->AddEvent("message: success");
span->End();Specify a state for a span
You can specify one of the following states for a span: trace::StatusCode::kUnset, trace::StatusCode::kOk, and trace::StatusCode::kError. trace::StatusCode::kUnset indicates the default state. trace::StatusCode::kOk indicates that the operation is successful. trace::StatusCode::kError indicates that an error occurs in the operation.
auto span = get_tracer()->StartSpan("<my operation>");
// do your stuff
// ...
span->SetStatus(trace::StatusCode::kError);
span->End();Propagate context
OpenTelemetry provides a text-based method to propagate context.
#include "opentelemetry/trace/context.h"
#include "opentelemetry/context/propagation/global_propagator.h"
#include "opentelemetry/context/propagation/text_map_propagator.h"
#include "opentelemetry/trace/propagation/http_trace_context.h"
#include "opentelemetry/nostd/shared_ptr.h"
// Use HttpTraceContext to demonstrate the basic usage of context propagation.
// Configure global propagator during SDK initialization.
opentelemetry::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator(
opentelemetry::nostd::shared_ptr<opentelemetry::context::propagation::TextMapPropagator>(
new opentelemetry::trace::propagation::HttpTraceContext()));
// Inject the header information when a network request is initiated on the client side.
opentelemetry::context::propagation::TextMapCarrier carrier; // Replace the value with your TextMapCarrier.
auto propagator = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator();
// Inject the header information.
auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent();
propagator->Inject(carrier, current_ctx);
// Extract the header information on the server side.
auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent();
auto new_context = propagator->Extract(carrier, current_ctx);
auto remote_span = opentelemetry::trace::GetSpan(new_context);OpenTelemetry SDK supports context propagation in compliance with the W3C Trace Context specification. For more information, see W3CTraceContextPropagator classes.
For more information about OpenTelemetry SDK, see Official documentation.