入门
本页面将向您展示如何在 C++ 中开始使用 OpenTelemetry。
您将学习如何为一个简单的 C++ 应用程序进行插桩,以便 跟踪 会被发送到终端。
先决条件
请确保您已在本地安装以下软件
- Git
- 支持 C++ 版本 >= 14 的 C++ 编译器
- Make
- CMake 版本 >= 3.25
示例应用程序
以下示例使用了一个基本的 Oat++ 应用程序。如果您不使用 Oat++,也没关系——您也可以将 OpenTelemetry C++ 与任何其他 Web 框架结合使用。
设置
创建一个名为
otel-cpp-starter的文件夹。进入新创建的文件夹。这将作为您的工作目录。
设置好依赖项后,您的目录结构应与此类似
otel-cpp-starter │ ├── oatpp ├── opentelemetry-cpp └── roll-dice
依赖项
首先,使用 源代码 和 make 在本地安装 Oat++,请按照以下步骤操作
通过克隆 oatpp/oatpp GitHub 存储库来获取 Oat++ 源代码。
git clone https://github.com/oatpp/oatpp.git导航到
oatpp目录,目前切换到 1.3.0 版本cd oatpp git checkout 1.3.0-latest创建一个
build子目录并进入其中。mkdir build cd build使用
cmake和make命令构建 oatpp。此命令将触发 oatpp 源代码中包含的CMakeLists.txt中指定的构建过程。cmake .. make安装 oatpp。
此命令将在您的系统上安装构建好的 oatpp 库和头文件,使其可用于您项目中的开发。
sudo make install
卸载您系统中已构建的 oatpp 库和头文件。
sudo make uninstall
接下来,使用 CMake 在本地安装并构建 OpenTelemetry C++,请按照以下步骤操作
在终端中,导航回
otel-cpp-starter目录。然后,将 OpenTelemetry C++ GitHub 存储库克隆到您的本地计算机。git clone https://github.com/open-telemetry/opentelemetry-cpp.git将您的工作目录更改为 OpenTelemetry C++ SDK 目录。
cd opentelemetry-cpp创建一个构建目录并进入其中。
mkdir build cd build在
build目录中运行 CMake,以配置和生成构建系统,而不启用测试cmake -DBUILD_TESTING=OFF ..或者,如果
cmake --build失败,您也可以尝试cmake -DBUILD_TESTING=OFF -DWITH_ABSEIL=ON ..执行构建过程
cmake --build .在 otel-cpp-starter/otel-cpp 中安装 OpenTelemetry C++
cmake --install . --prefix ../../otel-cpp
在 Oat++ 和 OpenTelemetry C++ 都准备就绪后,您可以继续创建 HTTP 服务器,这是我们最终想要进行插桩的。
创建并启动 HTTP 服务器
在您的 otel-cpp-starter 文件夹中,创建一个名为 roll-dice 的子文件夹,其中将通过引用 oatpp 头文件并在编译项目时链接它们来使用 Oat++ 库。
在 roll-dice 中创建一个名为 CMakeLists.txt 的文件,用于定义 Oat++ 库目录、包含路径,并在编译过程中链接 Oat++。
cmake_minimum_required(VERSION 3.25)
project(RollDiceServer)
# Set C++ standard (e.g., C++17)
set(CMAKE_CXX_STANDARD 17)
set(project_name roll-dice-server)
# Define your project's source files
set(SOURCES
main.cpp # Add your source files here
)
# Create an executable target
add_executable(dice-server ${SOURCES})
set(OATPP_ROOT ../oatpp)
find_library(OATPP_LIB NAMES liboatpp.a HINTS "${OATPP_ROOT}/build/src/" NO_DEFAULT_PATH)
if (NOT OATPP_LIB)
message(SEND_ERROR "Did not find oatpp library ${OATPP_ROOT}/build/src")
endif()
#set the path to the directory containing "oatpp" package configuration files
include_directories(${OATPP_ROOT}/src)
target_link_libraries(dice-server PRIVATE ${OATPP_LIB})
接下来,需要示例 HTTP 服务器源代码。它将执行以下操作
- 初始化一个 HTTP 路由器,并设置一个请求处理程序,以便在对
/rolldice端点发出 GET 请求时生成一个随机数作为响应。 - 接下来,创建一个连接处理程序、一个连接提供程序,并在 localhost:8080 上启动服务器。
- 最后,在 main 函数中初始化并运行应用程序。
在那个 roll-dice 文件夹中,创建一个名为 main.cpp 的文件,并将以下代码添加到该文件中。
#include "oatpp/web/server/HttpConnectionHandler.hpp"
#include "oatpp/network/Server.hpp"
#include "oatpp/network/tcp/server/ConnectionProvider.hpp"
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
class Handler : public oatpp::web::server::HttpRequestHandler {
public:
shared_ptr<OutgoingResponse> handle(const shared_ptr<IncomingRequest>& request) override {
int low = 1;
int high = 7;
int random = rand() % (high - low) + low;
// Convert a std::string to oatpp::String
const string response = to_string(random);
return ResponseFactory::createResponse(Status::CODE_200, response.c_str());
}
};
void run() {
auto router = oatpp::web::server::HttpRouter::createShared();
router->route("GET", "/rolldice", std::make_shared<Handler>());
auto connectionHandler = oatpp::web::server::HttpConnectionHandler::createShared(router);
auto connectionProvider = oatpp::network::tcp::server::ConnectionProvider::createShared({"localhost", 8080, oatpp::network::Address::IP_4});
oatpp::network::Server server(connectionProvider, connectionHandler);
OATPP_LOGI("Dice Server", "Server running on port %s", static_cast<const char*>(connectionProvider->getProperty("port").getData()));
server.run();
}
int main() {
oatpp::base::Environment::init();
srand((int)time(0));
run();
oatpp::base::Environment::destroy();
return 0;
}
使用以下 CMake 命令构建并运行应用程序。
mkdir build
cd build
cmake ..
cmake --build .
成功构建项目后,您可以运行生成的执行文件。
./dice-server
然后,在浏览器中打开 https://:8080/rolldice 以确保其正常工作。
仪表
要将 OpenTelemetry 添加到您的应用程序中,请使用以下附加依赖项更新 CMakeLists.txt 文件。
cmake_minimum_required(VERSION 3.25)
project(RollDiceServer)
# Set C++ standard (e.g., C++17)
set(CMAKE_CXX_STANDARD 17)
set(project_name roll-dice-server)
# Define your project's source files
set(SOURCES
main.cpp # Add your source files here
)
# Create an executable target
add_executable(dice-server ${SOURCES})
set(OATPP_ROOT ../oatpp)
set(opentelemetry-cpp_DIR ../otel-cpp/lib/cmake/opentelemetry-cpp)
find_library(OATPP_LIB NAMES liboatpp.a HINTS "${OATPP_ROOT}/build/src/" NO_DEFAULT_PATH)
if (NOT OATPP_LIB)
message(SEND_ERROR "Did not find oatpp library ${OATPP_ROOT}/build/src")
endif()
# set the path to the directory containing "oatpp" package configuration files
include_directories(${OATPP_ROOT}/src)
# Use find_package to include OpenTelemetry C++
find_package(opentelemetry-cpp CONFIG REQUIRED NO_DEFAULT_PATH)
# Link against each OpenTelemetry C++ library
target_link_libraries(dice-server PRIVATE
${OATPP_LIB}
${OPENTELEMETRY_CPP_LIBRARIES})
使用以下代码更新 main.cpp 文件,以初始化一个跟踪器并在调用 /rolldice 请求处理程序时发出 span。
#include "oatpp/web/server/HttpConnectionHandler.hpp"
#include "oatpp/network/Server.hpp"
#include "oatpp/network/tcp/server/ConnectionProvider.hpp"
#include "opentelemetry/exporters/ostream/span_exporter_factory.h"
#include "opentelemetry/sdk/trace/exporter.h"
#include "opentelemetry/sdk/trace/processor.h"
#include "opentelemetry/sdk/trace/simple_processor_factory.h"
#include "opentelemetry/sdk/trace/tracer_provider_factory.h"
#include "opentelemetry/trace/provider.h"
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
namespace trace_api = opentelemetry::trace;
namespace trace_sdk = opentelemetry::sdk::trace;
namespace trace_exporter = opentelemetry::exporter::trace;
namespace {
void InitTracer() {
auto exporter = trace_exporter::OStreamSpanExporterFactory::Create();
auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter));
std::shared_ptr<opentelemetry::trace::TracerProvider> provider =
trace_sdk::TracerProviderFactory::Create(std::move(processor));
//set the global trace provider
trace_api::Provider::SetTracerProvider(provider);
}
void CleanupTracer() {
std::shared_ptr<opentelemetry::trace::TracerProvider> none;
trace_api::Provider::SetTracerProvider(none);
}
}
class Handler : public oatpp::web::server::HttpRequestHandler {
public:
shared_ptr<OutgoingResponse> handle(const shared_ptr<IncomingRequest>& request) override {
auto tracer = opentelemetry::trace::Provider::GetTracerProvider()->GetTracer("my-app-tracer");
auto span = tracer->StartSpan("RollDiceServer");
int low = 1;
int high = 7;
int random = rand() % (high - low) + low;
// Convert a std::string to oatpp::String
const string response = to_string(random);
span->End();
return ResponseFactory::createResponse(Status::CODE_200, response.c_str());
}
};
void run() {
auto router = oatpp::web::server::HttpRouter::createShared();
router->route("GET", "/rolldice", std::make_shared<Handler>());
auto connectionHandler = oatpp::web::server::HttpConnectionHandler::createShared(router);
auto connectionProvider = oatpp::network::tcp::server::ConnectionProvider::createShared({"localhost", 8080, oatpp::network::Address::IP_4});
oatpp::network::Server server(connectionProvider, connectionHandler);
OATPP_LOGI("Dice Server", "Server running on port %s", static_cast<const char*>(connectionProvider->getProperty("port").getData()));
server.run();
}
int main() {
oatpp::base::Environment::init();
InitTracer();
srand((int)time(0));
run();
oatpp::base::Environment::destroy();
CleanupTracer();
return 0;
}
再次构建您的项目。
cd build
cmake ..
cmake --build .
成功构建项目后,您可以运行生成的执行文件。
./dice-server
当您向服务器发送请求至 https://:8080/rolldice 时,您将看到一个 span 被发送到终端。
{
"name" : "RollDiceServer",
"trace_id": "f47bea385dc55e4d17470d51f9d3130b",
"span_id": "deed994b51f970fa",
"tracestate" : ,
"parent_span_id": "0000000000000000",
"start": 1698991818716461000,
"duration": 64697,
"span kind": "Internal",
"status": "Unset",
"service.name": "unknown_service",
"telemetry.sdk.language": "cpp",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.11.0",
"instr-lib": "my-app-tracer"
}
下一步
有关插桩代码的更多信息,请参阅 插桩 文档。
您还需要配置一个合适的导出器,以 将您的遥测数据导出 到一个或多个遥测后端。