Skip to content
UCIK Docs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Logs and metrics with CloudWatch

Send logs and metrics and connect CloudWatch to game telemetry.

Finish AWS setup. Set Log Group, Log Stream, and Metric Namespace under AWS CloudWatch. Create the log group and stream, and grant the runtime role permission to write logs and metrics.

Use the Crossplay telemetry flow for player consent. Calling CloudWatch’s raw nodes directly does not pass through that consent gate.

Record a metric

Record match duration
Record match duration
Preparing your graph…

Loading the interactive viewer.

Flush queued records
Flush queued records
Preparing your graph…

Loading the interactive viewer.

Game module dependencies: UCIKCore, BetideCore, Engine.

#include "Engine/GameInstance.h"
#include "Telemetry/UCIKTelemetrySubsystem.h"
#include "UCIKCore.h"

void RecordMatchDuration(UGameInstance &GameInstance, double DurationSeconds)
{
    auto *Telemetry = GameInstance.GetSubsystem<UUCIKTelemetrySubsystem>();
    if (!Telemetry || !Telemetry->HasConsent())
        return;
    const FBetideError Error =
        Telemetry->RecordMetric(TEXT("MatchDurationSeconds"), DurationSeconds, {});
    if (Error.IsError())
    {
        UE_LOG(LogUCIK, Warning, TEXT("%s"), *Error.GetLogString());
    }
}

void FlushGameTelemetry(UGameInstance &GameInstance)
{
    auto *Telemetry = GameInstance.GetSubsystem<UUCIKTelemetrySubsystem>();
    if (!Telemetry)
        return;
    Telemetry->Flush(
        FBetideCallback<bool>::CreateWeakLambda(&GameInstance, [](const TBetideResult<bool> &Result) {
            if (!Result.bOk)
            {
                UE_LOG(LogUCIK, Warning, TEXT("%s"), *Result.Error.GetLogString());
                return;
            }
            UE_LOG(LogUCIK, Log, TEXT("Telemetry flushed: %d"), Result.GetValue());
        }));
}

Records are queued in memory. Call Flush Crossplay Telemetry at a checkpoint and wait for its result before treating delivery as complete. Do not rely on process exit to finish an upload.

Privacy, batching, and raw service calls

Allow PII defaults off and rejects events flagged as personal data. The CloudWatch adapter also redacts JSON fields whose names indicate secrets, tokens, email, or credentials, including nested fields. This is a key-name filter, not a guarantee that arbitrary payload text is safe.

Use a JSON object for events. Metrics require a finite value, a 1–255 character name, and at most 30 dimensions; sensitive dimension names are rejected. Max Batch Items controls request size. A full queue returns an error, so handle record failures as well as flush failures.

All processes using one configuration write to its configured log stream. Choose destinations deliberately for each environment. A second overlapping flush is rejected; wait for completion before starting another.

For direct service access, use Amazon CloudWatch Logs Put Log Events or Amazon CloudWatch Metrics Put Metric Data with their generated request types in AWSIKCloudWatch. These bypass UCIK’s consent and structured-event handling.

Direct server diagnostics

These examples send directly to CloudWatch. Set your own destinations in the request; the raw nodes do not read the telemetry adapter’s Log Group, Log Stream, or Metric Namespace settings. Create /mygame/server and dev-server-01 first, or replace them.

Upload a server queue-time metric
Upload a server queue-time metric
Preparing your graph…

Loading the interactive viewer.

Upload a server-ready log
Upload a server-ready log
Preparing your graph…

Loading the interactive viewer.

Game module dependencies: AWSIKCloudWatch, BetideCore, Engine.

#include "Engine/GameInstance.h"
#include "Generated/Metrics/Nodes/AWSIKCloudWatchMetricsMetricsNodes03.h"
#include "Generated/Events/Nodes/AWSIKCloudWatchLogsEventsNodes05.h"

void UploadServerQueueTime(UGameInstance &GameInstance, double QueueSeconds,
                           const FScriptDelegate &OnComplete)
{
    FAWSIKCloudWatchMetricsMetricDatum Metric;
    Metric.MetricName = TEXT("QueueTimeSeconds");
    Metric.bSetValue = true;
    Metric.Value = QueueSeconds;
    Metric.bSetUnit = true;
    Metric.Unit = EAWSIKCloudWatchMetricsStandardUnit::Seconds;
    FAWSIKCloudWatchMetricsPutMetricDataRequest Request;
    Request.Namespace = TEXT("MyGame/Server");
    Request.bSetMetricData = true;
    Request.MetricData.Add(MoveTemp(Metric));
    auto *Action = UAWSIKCloudWatchMetricsPutMetricData::PutMetricData(&GameInstance, Request);
    Action->OnSuccess.Add(OnComplete);
    Action->OnFailure.Add(OnComplete);
    Action->Activate();
}

void UploadServerReadyLog(UGameInstance &GameInstance, const FScriptDelegate &OnComplete)
{
    FAWSIKCloudWatchLogsInputLogEvent Event;
    Event.timestamp = FDateTime::UtcNow().ToUnixTimestamp() * 1000;
    Event.message = TEXT("{\"event\":\"ServerReady\",\"map\":\"Arena\"}");
    FAWSIKCloudWatchLogsPutLogEventsRequest Request;
    Request.logGroupName = TEXT("/mygame/server");
    Request.logStreamName = TEXT("dev-server-01");
    Request.logEvents.Add(MoveTemp(Event));
    auto *Action = UAWSIKCloudWatchLogsPutLogEvents::PutLogEvents(&GameInstance, Request);
    Action->OnSuccess.Add(OnComplete);
    Action->OnFailure.Add(OnComplete);
    Action->Activate();
}

bool WereLogEventsRejected(const FAWSIKCloudWatchLogsPutLogEventsResult &Result)
{
    const auto &Rejected = Result.rejectedLogEventsInfo;
    return Rejected.bSettooNewLogEventStartIndex || Rejected.bSettooOldLogEventEndIndex ||
           Rejected.bSetexpiredLogEventEndIndex;
}

Bind OnComplete to a UFUNCTION taking const FAWSIKCloudWatchMetricsEmptyResult& (metrics) or const FAWSIKCloudWatchLogsPutLogEventsResult& (logs), then const FAWSIKCloudWatchError&. Check Error.IsError() first and display Error.Common.Message. For logs, also check WereLogEventsRejected(Result) before reporting delivery.

Keep Value, Unit, and Metric Data enabled on the Make nodes. C++ sets their bSet... flags explicitly. Use a finite number for queue time; the metric timestamp is omitted so CloudWatch supplies it. New metrics can take time to appear in listings. Metric API details.

Log timestamps use Unix milliseconds. The example uploads one event and checks the three rejection flags; when batching, use their indices to identify rejected entries and sort events by timestamp. CloudWatch ignores sequence tokens. Log API details.

Was this page helpful?