入门

在不到 5 分钟内为您的应用获取遥测数据!

本页面将向您展示如何在 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++,请按照以下步骤操作

  1. 通过克隆 oatpp/oatpp GitHub 存储库来获取 Oat++ 源代码。

    git clone https://github.com/oatpp/oatpp.git
    
  2. 导航到 oatpp 目录,目前切换到 1.3.0 版本

    cd oatpp
    git checkout 1.3.0-latest
    
  3. 创建一个 build 子目录并进入其中。

    mkdir build
    cd build
    
  4. 使用 cmakemake 命令构建 oatpp。此命令将触发 oatpp 源代码中包含的 CMakeLists.txt 中指定的构建过程。

    cmake ..
    make
    
  5. 安装 oatpp。

此命令将在您的系统上安装构建好的 oatpp 库和头文件,使其可用于您项目中的开发。

sudo make install

卸载您系统中已构建的 oatpp 库和头文件。

sudo make uninstall

接下来,使用 CMake 在本地安装并构建 OpenTelemetry C++,请按照以下步骤操作

  1. 在终端中,导航回 otel-cpp-starter 目录。然后,将 OpenTelemetry C++ GitHub 存储库克隆到您的本地计算机。

    git clone https://github.com/open-telemetry/opentelemetry-cpp.git
    
  2. 将您的工作目录更改为 OpenTelemetry C++ SDK 目录。

    cd opentelemetry-cpp
    
  3. 创建一个构建目录并进入其中。

    mkdir build
    cd build
    
  4. build 目录中运行 CMake,以配置和生成构建系统,而不启用测试

    cmake -DBUILD_TESTING=OFF ..
    

    或者,如果 cmake --build 失败,您也可以尝试

    cmake -DBUILD_TESTING=OFF -DWITH_ABSEIL=ON ..
    
  5. 执行构建过程

    cmake --build .
    
  6. 在 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"
}

下一步

有关插桩代码的更多信息,请参阅 插桩 文档。

您还需要配置一个合适的导出器,以 将您的遥测数据导出 到一个或多个遥测后端。