文档

通过OpenTelemetry接入Unreal Engine Trace数据

更新时间:

本文介绍如何在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-winddows目录下。目录说明,如下所示。

重要

在创建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. 单击Actorimage

  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

  • 本页导读 (1)
文档反馈