Skip to content

Add Unreal MPS telemetry sample#97

Open
Copilot wants to merge 1 commit intomainfrom
copilot/add-unreal-sample-integration
Open

Add Unreal MPS telemetry sample#97
Copilot wants to merge 1 commit intomainfrom
copilot/add-unreal-sample-integration

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 30, 2026

PR #96 added a Unity MPS telemetry sample. This adds the Unreal equivalent: a drop-in dedicated server telemetry plugin intended to be wired into an existing GSDK-enabled Unreal server.

  • Unreal telemetry plugin

    • Added UnrealMpsTelemetry runtime plugin scaffold.
    • Provides UMpsTelemetrySubsystem for MPS lifecycle integration.
    • Reads telemetry keys from PF_MPS_SECRET_TelemetryKey or PLAYFAB_TELEMETRY_KEY.
  • Metrics collection

    • Captures aggregated server health metrics: uptime, tick count, average/max tick time, long-tick count, CPU core count, and memory stats.
    • Emits low-volume server_metrics_summary and server_metrics_final events.
    • Supports custom game/network metric providers.
  • PlayFab telemetry transport

    • Queues and batches telemetry events.
    • Sends events to WriteTelemetryEvents with X-TelemetryKey.
    • Requeues failed batches with bounded queue limits.
  • Documentation

    • Added Unreal integration guidance for GSDK startup/shutdown wiring.
    • Documented telemetry key setup, LocalMultiplayerAgent validation, Data Explorer queries, and production notes.
    • Linked the new sample from the root README.

Example integration:

UMpsTelemetrySubsystem* Telemetry =
    GetGameInstance()->GetSubsystem<UMpsTelemetrySubsystem>();

Telemetry->RegisterCustomMetricsProvider(
    [this](TSharedRef<FJsonObject> Payload)
    {
        Payload->SetNumberField(TEXT("networkActiveConnections"), NetworkServer->GetActiveConnectionCount());
        Payload->SetNumberField(TEXT("networkBytesReceived"), NetworkServer->GetAndResetBytesReceived());
        Payload->SetNumberField(TEXT("networkBytesSent"), NetworkServer->GetAndResetBytesSent());
    });

Telemetry->InitializeForMps(TitleId);

@dgkanatsios dgkanatsios force-pushed the copilot/add-unreal-sample-integration branch from 4dfa53f to 2aea7a9 Compare April 30, 2026 22:17
@dgkanatsios dgkanatsios marked this pull request as ready for review April 30, 2026 22:21
@dgkanatsios dgkanatsios requested a review from Copilot April 30, 2026 22:22
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds an Unreal Engine “drop-in” runtime plugin sample that collects dedicated-server metrics and flushes them to PlayFab Telemetry (WriteTelemetryEvents), mirroring the previously added Unity MPS telemetry sample.

Changes:

  • Added UnrealMpsTelemetry runtime plugin scaffold with UMpsTelemetrySubsystem for MPS lifecycle wiring.
  • Implemented metrics collection (tick/process stats) and a batching HTTP telemetry client with bounded queue + requeue-on-failure.
  • Added Unreal-specific documentation and linked the sample from the repo root README.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
UnrealMpsTelemetry/UnrealMpsTelemetry.uplugin Adds plugin descriptor for the Unreal telemetry sample.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/UnrealMpsTelemetry.Build.cs Declares runtime module dependencies needed for HTTP + JSON telemetry.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Public/MpsTelemetrySubsystem.h Introduces the public subsystem API for init/shutdown and custom metrics providers.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Private/MpsTelemetrySubsystem.cpp Wires tick + ticker-based periodic summary collection and flush behavior.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Public/MpsTelemetrySampleConfig.h Centralizes cadence, queue limits, and env-var telemetry key lookup.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Private/UnrealServerMetricsCollector.h Defines the metrics collector interface and interval counters.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Private/UnrealServerMetricsCollector.cpp Implements tick/process metric aggregation and custom provider invocation.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Private/PlayFabTelemetryClient.h Defines the batching/queueing telemetry transport client.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Private/PlayFabTelemetryClient.cpp Implements batching, HTTP POST to WriteTelemetryEvents, and retry/requeue.
UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Private/UnrealMpsTelemetryModule.cpp Adds module entry point and defines the plugin log category.
UnrealMpsTelemetry/README.md Documents integration steps, telemetry key setup, and validation queries.
UnrealMpsTelemetry/.gitignore Ignores Unreal plugin build artifacts.
README.md Links the new Unreal telemetry sample from the root documentation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Private/PlayFabTelemetryClient.cpp Outdated
Comment thread UnrealMpsTelemetry/Source/UnrealMpsTelemetry/Private/PlayFabTelemetryClient.cpp Outdated
dgkanatsios pushed a commit that referenced this pull request Apr 30, 2026
Fixes the four findings from the GitHub Copilot reviewer on PR #97:

1. PlayFabTelemetryClient.cpp - the HTTP completion lambda now captures a TSharedRef (not TWeakPtr) of the client. If the owning subsystem releases its TSharedPtr while a request is in flight (e.g. during Deinitialize), the dequeued batch was previously lost. The strong ref keeps the client alive until the request completes.

2. MpsTelemetrySubsystem.cpp - Deinitialize now calls BeginShutdown when the host did not, so server_metrics_final is always enqueued. Combined with completion chaining (see #1) and the strong-ref capture, in-flight and queued events keep flushing even after the subsystem releases its pointer.

3. PlayFabTelemetryClient.cpp - bFlushInProgress is now read and written under SyncRoot, including a single critical section that performs the in-progress check, dequeue, and flag flip together. Two concurrent FlushAsync calls can no longer both pull a batch and start parallel HTTP requests. The dedicated DequeueBatch helper is removed; ClearFlushInProgress is added so failure paths reliably reset the flag under the lock.

4. PlayFabTelemetryClient.cpp - the failure-path log truncates the response body to 512 chars to keep server logs bounded under sustained 5xx storms.

Also: the HTTP completion lambda now performs completion chaining. After clearing bFlushInProgress, if pending events remain (because new ones were enqueued, requeued after a failure, or queued by BeginShutdown after the periodic ticker was removed) it kicks off another FlushAsync. This is what drains the queue during shutdown without relying on a sleep-based poll loop, which would block the same game thread that delivers HTTP completions.

Not verified end-to-end on this commit (Unreal Engine has been uninstalled locally). Previous commits in this PR were verified against UE 5.7.4 + VS 2026; these changes are surgical and use only APIs already exercised in this plugin (FCriticalSection / FScopeLock, TSharedRef + AsShared, FString::Left). A teammate with Unreal installed should re-run the smoke test before merge.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds an Unreal Engine drop-in runtime plugin that collects dedicated-server engine and process metrics and flushes them to PlayFab telemetry (WriteTelemetryEvents). Mirrors the design of the previously merged Unity MPS telemetry sample.

Plugin layout under UnrealMpsTelemetry/:

- UnrealMpsTelemetry.uplugin and Source/UnrealMpsTelemetry/UnrealMpsTelemetry.Build.cs declare a runtime module depending only on Core, CoreUObject, Engine, HTTP, Json.

- Public/MpsTelemetrySubsystem.h exposes UMpsTelemetrySubsystem (UGameInstanceSubsystem + FTickableGameObject) with InitializeForMps(TitleId, ExternalEntityId), BeginShutdown, and RegisterCustomMetricsProvider.

- Public/MpsTelemetrySampleConfig.h centralizes cadence, queue limits, event namespace (custom.mps.unrealserver), and resolves the telemetry key from PF_MPS_SECRET_TelemetryKey, then PLAYFAB_TELEMETRY_KEY, then a source placeholder.

- Private/UnrealServerMetricsCollector.{h,cpp} aggregates uptime, tick count, average and max tick ms, long-tick count, processor count, process and available physical and virtual memory, and invokes registered custom metrics providers.

- Private/PlayFabTelemetryClient.{h,cpp} batches and POSTs events to https://<title>.playfabapi.com/Event/WriteTelemetryEvents with the X-TelemetryKey header. The queue is bounded; failed batches requeue with oldest-event-first eviction matching the Unity sample.

Sends one server_metrics_summary every 60 seconds and one server_metrics_final on BeginShutdown to keep telemetry cost bounded.

Robustness:

- TPimplPtr<FUnrealServerMetricsCollector> hides the private collector header from the public subsystem header without breaking UHT-generated code.

- Periodic summary and flush use FTSTicker so cadence is real-time and unaffected by world pause or time dilation.

- HTTP completion lambda captures a strong TSharedRef of the client so in-flight batches survive subsystem teardown, and chains another FlushAsync if events remain so the queue drains during shutdown without sleep-based polling.

- Deinitialize calls BeginShutdown when the host did not, ensuring server_metrics_final is always enqueued.

- bFlushInProgress and the dequeue path are protected by a single FCriticalSection so concurrent FlushAsync calls cannot start parallel HTTP requests, and failure paths reliably reset the flag.

- Failure-path log truncates the HTTP response body to 512 chars to keep server logs bounded under sustained 5xx storms.

Verified end-to-end against UE 5.7.4 + Visual Studio 2026 (Microsoft.VisualStudio.Workload.NativeGame): the plugin compiles, the subsystem initializes, and server_metrics_summary events arrive in PlayFab Data Explorer at the expected 60s cadence under namespace custom.mps.unrealserver.

Includes README with integration steps, telemetry key setup, an actual sanitized ingested-envelope sample captured from a verification run, and a Data Explorer KQL query.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants