本文介绍如何在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。
在工作负荷页签中,选中使用 C++ 的桌面开发和使用 C++ 的游戏开发这两个工作负荷。
在单个组件页签中,选中.Net Framework 4.8 SDK和.NET Core 3.1 Runtime。
步骤二:获取OpenTelemetry C++ SDK二进制文件
目前,您可以通过如下两种方式获取OpenTelemetry C++ SDK的二进制文件。
通过OpenTelemetry C++源码进行编译与构建二进制文件。
推荐您使用该方式,以便OpenTelemetry C++ SDK能够与您的项目完全兼容。
通过vcpkg包管理器获取二进制文件。
OpenTelemetry C++ SDK的CMake文件提供多个入参,方便您在编译时进行配置。您可以参考以下配置,进行构建。
OpenTelemetry C++ SDK的源码版本是v1.9.0。
创建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
构建CMake目标。
$ cmake --build . --config Release -j
安装API头文件。
$ cmake --install .
执行以上命令成功后,构建产物将被打包在CMAKE_INSTALL_PREFIX指定的文件夹中。目录说明,如下所示。
在创建UE插件时,您需要复制此处的文件。
bin/目录:包含动态链接库(.dll文件)。
lib/目录:包含静态链接库文件(.lib文件)。
include/目录:包含头文件(.h文件)。
关于OpenTelemetry C++ SDK编译构建的更多信息,请参见Building opentelemetry-cpp。
从vcpkg包获取到的SDK二进制文件,可能与您的项目存在兼容性问题,建议您充分测试后再使用。更多信息,请参见using-package-managers。
在您的工作目录中,打开一个command prompt或者terminal。
使用Git克隆vcpkg包。
$ git clone https://github.com/microsoft/vcpkg
执行bootstrap-vcpkg.bat脚本,如下图所示。
$ .\vcpkg\bootstrap-vcpkg.bat
进入到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
。您需要按照您项目的实际名称进行配置。
新建插件
打开您的UE项目。
在页面左上角,选择编辑 > 插件。
在插件管理面板,单击新插件。
单击空白。
配置插件名称。
您可以自定义插件名称(例如OTelPlugin),但需确保其唯一性。
单击创建插件。
创建插件后,系统会在工程的Plugins目录下创建OTelPlugin目录。
如果Plugins目录下无OTelPlugin目录,说明您的项目是一个蓝图(Blueprint-only)项目,或者您创建的插件类型为纯内容(content-only),请对项目类型以及插件类型进行再次确认。
打开UEExampleProject/OTelPlugin/Source目录,完成如下操作。
在当前目录下,新增OTelSDK文件夹。
在OTelSDK文件夹内,新增include文件夹、lib文件夹及OTelSDK.Build.cs文件。
将步骤二中生成的bin/和lib/文件夹中的静态及动态链接库文件(.lib和.dll文件)复制到您在步骤7中所创建的lib文件夹下的平台文件夹中。
配置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")); } }
配置项目
打开UEExampleProject.Build.cs文件。
在UEExampleProject.Build.cs文件中,导入您已创建的OTelSDK模块,作为依赖。
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; CppStandard = CppStandardVersion.Cpp17; PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "OTelSDK" });
返回您项目的根目录,右键单击UEExampleProject.uproject文件,然后单击Generate Visual Studio project files。
重新打开您的项目,Visual Studio会自动重新加载您的项目。
步骤四:验证插件
在包含OTelSDK插件模块作为依赖项的任何模块中,创建一个新的C++ Actor。
在内容浏览器中,创建一个C++类。
单击Actor。
设置Actor名称,然后选择目标模块。
在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。
无
<your accesskey secret>
阿里云账号AccessKey Secret。
建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey。
无
将Actor拖拽到关卡窗口视图中,然后单击运行。
在日志服务控制台的Trace服务应用中,查看Trace数据。
添加过滤条件
service : "MyActor"
,查看已接入的UE Trace数据。
- 本页导读 (1)
- 前提条件
- 步骤一:配置Visual Studio
- 步骤二:获取OpenTelemetry C++ SDK二进制文件
- 步骤三:使用OpenTelemetry C++ SDK创建UE插件
- 准备工作
- 新建插件
- 配置项目
- 步骤四:验证插件