帮助文档 Logo
平台使用
阿里云
百度云
移动云
智算服务
教育生态
登录 →
帮助文档 Logo
平台使用 阿里云 百度云 移动云 智算服务 教育生态
登录
  1. 首页
  2. 阿里云
  3. 日志服务
  4. 操作指南
  5. 日志应用
  6. 全栈可观测
  7. Trace
  8. 接入Trace数据
  9. 新接入方案
  10. 通过OpenTelemetry接入Unreal Engine Trace数据

通过OpenTelemetry接入Unreal Engine Trace数据

  • 新接入方案
  • 发布于 2025-04-22
  • 0 次阅读
文档编辑
文档编辑

本文介绍如何在Unreal Engine(UE)中集成OpenTelemetry C++ SDK以采集引擎的Trace数据。

前提条件

  • 已创建Trace实例。具体操作,请参见创建Trace实例。

  • 已准备相关的开发环境,该环境需要支持编译和运行OpenTelemetry C++ SDK。

    • 如果您使用的是CMake编译器,则其版本需为3.1及以上(建议)。

    • 如果您使用的是GCC或G++编译器,则其版本需要为4.8及以上。

    • 如果您使用的是MSVC,则其版本需要为VS2015及以上(建议为VS2019)。

  • 支持的C++版本如下所示。

    • 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)

  • 已安装Git版本控制工具。

  • 更多依赖及版本信息,请参见opentelemetry-cpp。

步骤一:配置Visual Studio

修改Visual Studio的配置。关于修改Visual Studio工作负荷和组件的具体操作,请参见修改Visual Studio。

  1. 在工作负荷页签中,选中使用 C++ 的桌面开发和使用 C++ 的游戏开发这两个工作负荷。imageimage

  2. 在单个组件页签中,选中.Net Framework 4.8 SDK和.NET Core 3.1 Runtime。image

步骤二:获取OpenTelemetry C++ SDK二进制文件

目前,您可以通过如下两种方式获取OpenTelemetry C++ SDK的二进制文件。

  • 通过OpenTelemetry C++源码进行编译与构建二进制文件。

    推荐您使用该方式,以便OpenTelemetry C++ SDK能够与您的项目完全兼容。

  • 通过vcpkg包管理器获取二进制文件。

(推荐)通过OpenTelemetry C++源码进行编译与构建二进制文件

OpenTelemetry C++ SDK的CMake文件提供多个入参,方便您在编译时进行配置。您可以参考以下配置,进行构建。

说明

OpenTelemetry C++ SDK的源码版本是v1.9.0。

  1. 创建CMake配置。

    $ cmake .. -T"v142" `
    $ -DCMAKE_INSTALL_PREFIX=./out `
    $ -DWITH_EXAMPLES:BOOL=OFF `
    $ -DWITH_OTLP:BOOL=ON `
    $ -DWITH_OTLP_GRPC:BOOL=ON `
    $ -DWITH_OTLP_HTTP:BOOL=ON `
    $ -DWITH_STL:BOOL=ON `
    $ -Dc-ares_DIR:PATH=<your c-ares path> `
    $ -Dre2_DIR:PATH=<your re2 path> `
    $ -DgRPC_DIR:PATH=<your gRPC path> `
    $ -Dabsl_DIR:PATH=<your absl path> 
    $ -DWITH_ABSEIL:BOOL=ON `
    $ -Dnlohmann_json_DIR:PATH=<your nlohmann_json path> `
    $ -DCURL_DIR:PATH=<your curl path> `
    $ -DOPENSSL_ROOT_DIR:PATH=<your openssl path> `
    $ -DOPENSSL_USE_STATIC_LIBS:BOOL=ON ` //建议
    $ -DProtobuf_DIR:PATH=<your proto path> `
    $ -DProtobuf_PROTOC_EXECUTABLE:FILEPATH=<your protoc exe filepath> `
    $ -DPROTO_INCLUDE_DIR:FILEPATH=<your proto filepath> `
    $ -DCMAKE_CXX_FLAGS=D_HAS_EXCEPTIONS=0 `
    $ -DgRPC_CPP_PLUGIN_EXECUTABLE:FILEPATH=<your grpc plugin exe filepath> `
    $ -DgRPC_ZLIB_PROVIDER=package `
    $ -DZLIB_ROOT=<your zlib install path> `
    $ -DZLIB_USE_STATIC_LIBS=True `
    $ -DZLIB_LIBRARY_RELEASE=<your zlib release lib path> `
    $ -DZLIB_LIBRARY_DEBUG=<your zlib debug lib path>

    其中,模块列表如下表所示。

    依赖项

    版本Tag

    zlib

    v1.2.13

    openssl

    1_1_1t

    cares

    1_19_0

    curl

    7_88_1

    nlohmann

    v3.11.2

    utf8_range

    main

    abseil

    20230125.2

    protobuf

    v21.12

    re2

    2022-12-01

    grpc

    v1.52.1

  2. 构建CMake目标。

    $ cmake --build . --config Release -j
  3. 安装API头文件。

    $ cmake --install .

执行以上命令成功后,构建产物将被打包在CMAKE_INSTALL_PREFIX指定的文件夹中。目录说明,如下所示。

重要

在创建UE插件时,您需要复制此处的文件。

  • bin/目录:包含动态链接库(.dll文件)。

  • lib/目录:包含静态链接库文件(.lib文件)。

  • include/目录:包含头文件(.h文件)。

关于OpenTelemetry C++ SDK编译构建的更多信息,请参见Building opentelemetry-cpp。

通过vcpkg包管理器获取二进制文件

重要

从vcpkg包获取到的SDK二进制文件,可能与您的项目存在兼容性问题,建议您充分测试后再使用。更多信息,请参见using-package-managers。

  1. 在您的工作目录中,打开一个command prompt或者terminal。

  2. 使用Git克隆vcpkg包。

    $ git clone https://github.com/microsoft/vcpkg
  3. 执行bootstrap-vcpkg.bat脚本,如下图所示。

    $ .\vcpkg\bootstrap-vcpkg.bat

    image

  4. 进入到vcpkg目录,并执行以下脚本内容。

    $ .\vcpkg.exe install opentelemetry-cpp[otlp-http]:x64-windows --recurse

执行以上命令成功后,OpenTelemetry C++ SDK以及对应的依赖SDK将被安装到vcpkg/installed/x64-windows目录下。目录说明,如下所示。

重要

在创建UE插件时,您需要复制此处的文件。

  • bin/目录:包含动态链接库(.dll文件)。

  • lib/目录:包含静态链接库文件(.lib文件)。

  • include/目录:包含头文件(.h文件)。

步骤三:使用OpenTelemetry C++ SDK创建UE插件

将OpenTelemetry C++ SDK集成到UE插件模块中。UE插件模块可以包含源代码或外部依赖项。

准备工作

在创建前,需先确认您的UE项目是C++项目,而不是蓝图(Blueprint-only)项目。您可以在使用Unreal Editor创建项目时进行指定。

本示例中,项目名称为UEExampleProject。您需要按照您项目的实际名称进行配置。

image

新建插件

  1. 打开您的UE项目。

  2. 在页面左上角,选择编辑 > 插件。

  3. 在插件管理面板,单击新插件。

  4. 单击空白。image

  5. 配置插件名称。

    您可以自定义插件名称(例如OTelPlugin),但需确保其唯一性。

  6. 单击创建插件。

    创建插件后,系统会在工程的Plugins目录下创建OTelPlugin目录。

    重要

    如果Plugins目录下无OTelPlugin目录,说明您的项目是一个蓝图(Blueprint-only)项目,或者您创建的插件类型为纯内容(content-only),请对项目类型以及插件类型进行再次确认。

  7. 打开UEExampleProject/OTelPlugin/Source目录,完成如下操作。

    1. 在当前目录下,新增OTelSDK文件夹。

    2. 在OTelSDK文件夹内,新增include文件夹、lib文件夹及OTelSDK.Build.cs文件。image

    3. 将步骤二中生成的include文件夹中的头文件(.h 文件)复制到您在步骤7中所创建的include文件夹中。image

    4. 将步骤二中生成的bin/和lib/文件夹中的静态及动态链接库文件(.lib和.dll文件)复制到您在步骤7中所创建的lib文件夹下的平台文件夹中。image

    5. 配置OTel.Build.cs文件,示例如下所示。

      using System;
      using System.IO;
      using UnrealBuildTool;
      
      public class OTelSDK : ModuleRules {
      
          public OTelSDK(ReadOnlyTargetRules Target) : base(Target) {
      		Type = ModuleType.External;
      		CppStandard = CppStandardVersion.Cpp17;
      
      		// OpenTelemetry is built with STL support.
      		// This convinces the headers of this fact.
      		PublicDefinitions.Add("HAVE_CPP_STDLIB=1");
      
      		// include path is public for the module. Can it be private and 
      		// still be used by other modules of the same plugin?
      		PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "include"));
      
      		// configure link libraries. This basically makes it windows x64 only
      		string LibrariesPath = Path.Combine(ModuleDirectory, "lib", "Win64");
      		
          // OpenTelemetry
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_common.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_in_memory.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_ostream_span.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_otlp_grpc.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_otlp_grpc_client.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_otlp_grpc_log.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_otlp_grpc_metrics.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_otlp_http.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_otlp_http_client.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_exporter_otlp_http_metric.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_metrics.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_http_client_curl.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_otlp_recordable.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_proto.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_resources.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_trace.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "opentelemetry_version.lib"));
      
      		// Abseil.
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_bad_any_cast_impl.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_bad_optional_access.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_bad_variant_access.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_base.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_city.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_civil_time.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_cord.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_cord_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_cordz_functions.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_cordz_handle.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_cordz_info.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_cordz_sample_token.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_crc_cord_state.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_crc_cpu_detect.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_crc_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_crc32c.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_debugging_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_demangle_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_examine_stack.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_exponential_biased.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_graphcycles_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_hash.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_low_level_hash.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_hashtablez_sampler.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_int128.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_malloc_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_raw_hash_set.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_raw_logging_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_distributions.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_internal_platform.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_internal_pool_urbg.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_internal_randen.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_internal_randen_hwaes.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_internal_randen_hwaes_impl.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_internal_randen_slow.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_internal_seed_material.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_random_seed_gen_exception.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_scoped_set_env.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_spinlock_wait.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_stacktrace.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_status.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_statusor.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_strerror.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_strings.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_strings_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_str_format_internal.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_symbolize.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_synchronization.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_throw_delegate.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_time.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "absl_time_zone.lib"));
      
      		// OpenSSL
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "libcrypto.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "libssl.lib"));
      		PublicSystemLibraries.Add("crypt32.lib");   // indirect dependencies coming in via OpenSSL. Windows only.
      		PublicSystemLibraries.Add("Wldap32.lib");
      
      		// GRPC
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "address_sorting.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "cares.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "gpr.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc++.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc++_alts.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc++_error_details.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc++_reflection.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc++_unsecure.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpcpp_channelz.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc_plugin_support.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc_unsecure.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "grpc_authorization_provider.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "re2.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "upb.lib"));
      
      		// Protobuf
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "libprotobuf.lib"));
      
      		// utf8-range
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "utf8_range.lib"));
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "utf8_validity.lib"));
      		
      		// CURL
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "libcurl.lib"));
      
      		// Crc32c
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "crc32c.lib"));
      
      		// ZLib
      		PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "zlibstatic.lib"));
      	}
      }

配置项目

  1. 打开UEExampleProject.Build.cs文件。image

  2. 在UEExampleProject.Build.cs文件中,导入您已创建的OTelSDK模块,作为依赖。

    PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    
    CppStandard = CppStandardVersion.Cpp17;
    PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "OTelSDK" });
  3. 返回您项目的根目录,右键单击UEExampleProject.uproject文件,然后单击Generate Visual Studio project files。

  4. 重新打开您的项目,Visual Studio会自动重新加载您的项目。

步骤四:验证插件

在包含OTelSDK插件模块作为依赖项的任何模块中,创建一个新的C++ Actor。

  1. 在内容浏览器中,创建一个C++类。image

  2. 单击Actor。image

  3. 设置Actor名称,然后选择目标模块。image

  4. 在MyActor.cpp文件中完成如下配置。

    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "MyActor.h"
    #pragma once
    
    #include "opentelemetry/exporters/ostream/span_exporter_factory.h"
    #include "opentelemetry/exporters/otlp/otlp_http.h"
    #include "opentelemetry/exporters/otlp/otlp_http_exporter_factory.h"
    #include "opentelemetry/exporters/otlp/otlp_http_exporter_options.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"
    
    #include "opentelemetry/sdk/common/global_log_handler.h"
    
    class CustomLogHandler : public opentelemetry::sdk::common::internal_log::LogHandler
    {
    public:
        void Handle(opentelemetry::sdk::common::internal_log::LogLevel level,
            const char*,
            int,
            const char* msg,
            const opentelemetry::sdk::common::AttributeMap& attrs) noexcept override
        {
            UE_LOG(LogTemp, Log, TEXT("%s"), *FString(msg));
        }
    };
    
    namespace trace = opentelemetry::trace;
    namespace trace_sdk = opentelemetry::sdk::trace;
    namespace otlp = opentelemetry::exporter::otlp;
    namespace trace_exporter = opentelemetry::exporter::trace;
    namespace resource = opentelemetry::sdk::resource;
    
    namespace
    {
        opentelemetry::exporter::otlp::OtlpHttpExporterOptions opts;
        void InitTracer()
        {
            // custome log handler
            using opentelemetry::sdk::common::internal_log::LogHandler;
            auto custom_log_handler = opentelemetry::nostd::shared_ptr<LogHandler>(new CustomLogHandler{});
            opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogHandler(custom_log_handler);
            opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogLevel(opentelemetry::sdk::common::internal_log::LogLevel::Debug);
    
            opts.url = "https://<your project>.<your endpoint>/opentelemetry/v1/traces";
            opts.console_debug = true;
            opts.content_type = otlp::HttpRequestContentType::kBinary;
            // Setup credentials info
            opts.http_headers.insert(std::pair<std::string, std::string>("x-sls-otel-project", "<your project>"));
            opts.http_headers.insert(std::pair<std::string, std::string>("x-sls-otel-instance-id", "<your instance id>"));
            opts.http_headers.insert(std::pair<std::string, std::string>("x-sls-otel-ak-id", "<your accesskey id>"));
            opts.http_headers.insert(std::pair<std::string, std::string>("x-sls-otel-ak-secret", "<your accesskey secret>"));
    
            // Create OTLP exporter instance
            auto exporter = otlp::OtlpHttpExporterFactory::Create(opts);
            //auto exporter = trace_exporter::OStreamSpanExporterFactory::Create();
            auto processor = trace_sdk::SimpleSpanProcessorFactory::Create(std::move(exporter));
    
            resource::ResourceAttributes attributes = {
              {resource::SemanticConventions::kServiceName, "MyActor"},
              {resource::SemanticConventions::kServiceNamespace, "UE Games"},
              {resource::SemanticConventions::kServiceVersion, "1.0.0"},
              {resource::SemanticConventions::kHostName, "Win64"},
              {resource::SemanticConventions::kDeploymentEnvironment, "dev"}
            };
            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);
        }
    }  // namespace
    
    namespace trace = opentelemetry::trace;
    namespace nostd = opentelemetry::nostd;
    
    namespace
    {
        nostd::shared_ptr<trace::Tracer> get_tracer()
        {
            auto provider = trace::Provider::GetTracerProvider();
            return provider->GetTracer("foo_library", OPENTELEMETRY_SDK_VERSION);
        }
    
        void basic_f1()
        {
            auto span = get_tracer()->StartSpan("basic_f1");
            // do your stuff
            // ...
            span->End();
        }
    
        void basic_f1_with_attributes()
        {
            auto span = get_tracer()->StartSpan("basic_f1_with_attributes");
            span->SetAttribute("ags", 12);
            span->SetAttribute("sex", "man");
            span->SetAttribute("height", 154.5);
    
    
            span->AddEvent("message: success");
    
            span->SetStatus(trace::StatusCode::kError);
    
            span->End();
        }
    
        void basic_active_f1()
        {
            auto span_child = get_tracer()->StartSpan("operation B");
            // do your stuff
            // ...
            span_child->End();
        }
    
        void basic_active()
        {
            auto span = get_tracer()->StartSpan("operation A");
            auto scope = get_tracer()->WithActiveSpan(span);
    
            basic_active_f1();
    
            span->End();
        }
    
    
        void f1()
        {
            auto scoped_span = trace::Scope(get_tracer()->StartSpan("f1"));
        }
    
        void f2()
        {
            auto scoped_span = trace::Scope(get_tracer()->StartSpan("f2"));
    
            f1();
            f1();
        }
    }  // namespace
    
    void foo_library()
    {
    
        basic_f1();
        basic_active();
        basic_f1_with_attributes();
    
        auto scoped_span = trace::Scope(get_tracer()->StartSpan("library"));
    
        f2();
    
    }
    
    // Sets default values
    AMyActor::AMyActor()
    {
        // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
        UE_LOG(LogTemp, Log, TEXT("debuggg ---  AMyActor  ---"));
        InitTracer();
        foo_library();
    }
    
    // Called when the game starts or when spawned
    void AMyActor::BeginPlay()
    {
        Super::BeginPlay();
        UE_LOG(LogTemp, Log, TEXT("debuggg ---  BeginPlay ---"));
    
        foo_library();
    
        //CleanupTracer();
    
    }
    
    // Called every frame
    void AMyActor::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);
    
    }

    变量说明如下表所示。关于OpenTelemetry C++ SDK的更多信息,请参见步骤三:使用SDK以及OpenTelemetry C++ SDK。

    参数

    说明

    示例

    <your endpoint>

    日志服务Project所在地域的访问域名,支持公网和阿里云内网(经典网络、VPC)。更多信息,请参见服务入口。

    重要

    此处无需添加https://前缀。

    cn-hangzhou.log.aliyuncs.com

    <your project>

    日志服务Project名称。

    sls-ue-demo

    <your instance id>

    Trace服务实例ID。更多信息,请参见创建Trace实例。

    ue-traces

    <your accesskey id>

    阿里云账号AccessKey ID。

    重要

    建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey(包括AccessKey ID和AccessKey Secret)。授予RAM用户向指定Project写入数据权限的具体操作,请参见授权。如何获取AccessKey的具体操作,请参见访问密钥。

    无

    <your accesskey secret>

    阿里云账号AccessKey Secret。

    重要

    建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey。

    无

  5. 将Actor拖拽到关卡窗口视图中,然后单击运行。image

  6. 在日志服务控制台的Trace服务应用中,查看Trace数据。

    添加过滤条件 service : "MyActor" ,查看已接入的UE Trace数据。image

相关文章

通过OpenTelemetry接入Java Trace数据 2025-04-22 10:45

本文介绍通过OpenTelemetry Java SDK将Java应用的Trace数据接入到日志服务的操作步骤。 前提条件

通过OpenTelemetry接入Golang Trace数据 2025-04-22 10:45

本文介绍通过OpenTelemetry Golang SDK将Golang应用的Trace数据接入到日志服务的操作步骤。 前提条件

通过OpenTelemetry接入Python Trace数据 2025-04-22 10:45

本文介绍通过OpenTelemetry Python SDK将Python应用的Trace数据接入到日志服务的操作步骤。 前提条件

通过OpenTelemetry接入Node.js Trace数据 2025-04-22 10:45

本文介绍通过opentelemetry-js SDK将Node.js应用的Trace数据接入到日志服务的操作步骤。 前提条件

通过OpenTelemetry接入C# Trace数据 2025-04-22 10:45

本文介绍通过OpenTelemetry .NET SDK将C#应用的Trace数据接入到日志服务的操作步骤。 前提条件

通过OpenTelemetry接入Rust Trace数据 2025-04-22 10:45

本文介绍通过OpenTelemetry Rust SDK将Rust应用的Trace数据接入到日志服务的操作步骤。 前提条件

目录
Copyright © 2025 your company All Rights Reserved. Powered by 博智数字服务平台.
闽ICP备08105208号-1