Skip to content
Stove
Last Updated

Log

Understanding


Using the log feature provided by the STOVE SDK, you can collect and analyze players' in-game behavior and key events.
The collected data is sent to the STOVE platform's analytics system, and based on it the game operator can assess content status, measure event effectiveness, detect anomalous metrics, and more.
Logs support both Mobile (Android/iOS) and PC, and the provision method differs by platform.

Log Types

Type Description
Standard event log An event schema predefined by STOVE. Records game-common behaviors such as tutorial completion and level-up
Custom event log Events the game defines freely. Collects game-specific behaviors and metrics
User-attribute log Sets player attribute values such as level, class, and payment tier. Automatically included in subsequent events for segment analysis

Cautions when designing logs
ㅁ Don't include personally identifiable information (name, contact, etc.) in log parameters.
ㅁ We recommend predefining event names and parameters in a planning document. Changing an event name can cause a mismatch with previously collected data.

Provision Method by Platform

Item Mobile PC
SDK Mobile SDK 2.0.0 or higher PC SDK (Log module)
Supported platforms Android (Kotlin/Java), iOS, Unity, Unreal Native C/C++, Unity, Unreal
Initialization order Logs can be called after the user's login completes Base SDK initialization → Log SDK initialization order is required
Transmission method Sent to the STOVE log-collection server after asynchronous processing inside the SDK Sent to the STOVE log-collection server after asynchronous processing inside the SDK
Offline handling Same for Mobile and PC · When the network is unstable, stored in an internal queue and automatically resent on recovery (up to 1,000 entries)

Initialization is required before using logs
ㅁ Initialize the log feature once at app start before use. (common to Mobile and PC)
ㅁ On PC, you must first complete Base SDK integration/initialization before you can initialize the Log SDK.

Development


Mobile — Setting the External Identifier (setExternalId)

The STOVE Mobile SDK automatically collects core logs inside the platform. For cross-analysis purposes, it provides the Log.setExternalId() interface so you can include an externally managed identifier (e.g., an MMP user ID) in log events. (Log v2.8.2 or higher) After the call, the external identifier is automatically attached to all subsequent logs.


Prerequisites

  • You must finish setting the external identifier by calling Log.setExternalId() before calling Auth.initialize(). If you call it after initialization, some early logs won't include the identifier.
  • The external-identifier value is issued and managed by the game/service. The SDK doesn't validate it separately.
  • The external identifier is set globally in the SDK and persists per process.

External-identifier constraints

  • String length: up to 64 characters
  • Allowed characters: uppercase/lowercase letters, digits, hyphen (-), underscore (_)
  • Spaces and special characters aren't allowed

Development Flow

  1. Secure the external identifier: prepare the external-identifier value issued by the game/service. (e.g., an MMP user ID)
  2. Call Log.setExternalId(externalId): set the identifier before calling Auth.initialize().
  3. Proceed with auth initialization: from Auth.initialize() onward, proceed with the normal auth/log flow as-is, and the external identifier is automatically included in the logs that occur.

When receiving the identifier asynchronously
If you receive the external identifier via a network response or asynchronous API, adjust the boot sequence so that Auth.initialize() is called after the response completes. Otherwise, the identifier will be missing from early logs by however long the response is delayed.


Troubleshooting

SituationCauseSolution
Some early logs are missing the external identifierYou called Log.setExternalId() after calling Auth.initialize(). Logs that occurred before the identifier was set don't include the external identifier.Move Log.setExternalId() to the very front of the boot sequence and call Auth.initialize() only after the identifier is set. If you receive the external identifier asynchronously, adjust the flow so Auth.initialize() is called after the response arrives.
The external identifier isn't applied or gets truncatedIt exceeded 64 characters, or included Korean, spaces, or special characters.Compose the identifier only of uppercase/lowercase letters, digits, hyphen (-), and underscore (_), and keep it to 64 characters or fewer. Validate it with a regex at the issuance stage before passing it to the SDK.

Sample Code

csharp
string externalId = "external-id-12345";
Log.SetExternalId(externalId);

PC (PCSDK)

Prerequisites

  • Log transmission is possible only after you initialize the LogSDK (Log_Initialize) once BaseSDK initialization (Base_Initialize) completes. Calling Log_Initialize() before BaseSDK initialization finishes fails initialization.
  • Base_RunCallback() must be called periodically in the game loop for the log-transmission result callback to work correctly.
  • For cleanup, clean up the LogSDK with Log_UnInitialize(), then clean up BaseSDK with Base_UnInitialize().
  • The LogSDK provides two log-related functions: transmission and version lookup, namely Log_Send / Log_GetVersion. User attributes, flush, debug mode, etc. are Mobile-SDK-only; on PC, the game includes them directly in the log item and sends them.

Development Flow

  1. Initialization: You can send logs only after initializing the LogSDK (Log_Initialize()) once BaseSDK initialization (Base_Initialize()) completes.
  2. Log transmission: Set metadata such as game version and server code, plus additional data (a contents JSON string), in the log-item parameter (StovePCLogSendParam), and send the log (Log_Send()).
  3. Result handling: Verify success via the result object in the callback. On failure, branch by error code.
  4. Cleanup: Right before the game exits, clean up the LogSDK with Log_UnInitialize(), then clean up BaseSDK with Base_UnInitialize().

PC composes logs with fixed fields and a contents JSON
PC's StovePCLogSendParam doesn't take event names and key-value parameters directly like mobile. It provides fixed fields such as identifiers (auid, cuid), marketing integration (mktType1/mktId1/mktType2/mktId2), game info (gameVersion, serverCd, serverCdDet, lvCd, lvCdDet), and log mapping (logGroupId), while other data is sent as a JSON string in contents. All fields are optional, so fill in only the values you need for your game. Values that correspond to user attributes (level, class, payment tier, etc.) are also included directly in the log item and sent by the game.


Troubleshooting

SituationCauseSolution
The first log transmission right after game start returns BASE_NOT_INITIALIZED (16)You called a LogSDK API before BaseSDK initialization finished. The LogSDK depends on the auth/session info provided by BaseSDK.Call Base_Initialize to complete BaseSDK initialization, then initialize the LogSDK with Log_Initialize and send logs. Initializing in the order BaseSDK → LogSDK in the game boot sequence avoids issues.
NOT_INITIALIZED (17) is returnedYou called log transmission before LogSDK initialization (Log_Initialize) finished. The LogSDK must be initialized separately after BaseSDK initialization completes.Complete BaseSDK initialization with Base_Initialize, then initialize the LogSDK with Log_Initialize and send logs.
Log transmission returns INVALID_LOG_PARAMETER (85)You violated the event-name/key naming rules (letters/digits/underscore, length limit) or included Korean or special characters. A space in a parameter key causes the same error.Write event names and keys only within [A-Za-z0-9_]. Managing parameter names as constants and self-validating with a regex avoids issues.
A log is rejected with LOG_SIZE_EXCEEDED (86)An event has too many parameters, or a String value exceeded the length limit. It often happens when free text (chat messages, etc.) is sent as-is.Reduce the number of parameters to key metrics, and trim long Strings by summarizing, hashing, or truncating before sending. Rather than packing all context into one event, splitting it into separate events avoids issues.
Log transmission temporarily fails with HTTP_ERROR (22)A failure occurred at the communication stage, such as user network disconnection, proxy blocking, or a temporary STOVE-server outage.The LogSDK backs up failed logs to the local DB and automatically resends them at the next opportunity. On the game side, not blocking the user's screen and letting it retry naturally on the next call avoids issues.
LOCAL_DB_BACKUP_LOG_FAILED (84) is returnedIt occurs when the disk is full or the game install path has no write permission (read-only folder, missing admin rights, etc.).Since logs can't be backed up locally in this environment, logs may be lost if communication drops. Notify the game operations team and, from the next build, guide installation to a writable path such as the user folder (%APPDATA%).
I sent a log but the result callback isn't calledIf you don't call Base_RunCallback() in the game main loop, the SDK can't find a point to deliver the result to the game.Call Base_RunCallback() every frame or at a regular interval in the main loop. Calling it once between input handling and rendering avoids issues.

Sample Code

cpp
// Legacy C/C++ API (~3.4.x)
#include "LogSDK.h"

using namespace Stove::PCSDK;
using namespace Stove::PCSDK::Base;
using namespace Stove::PCSDK::Log;

// 1) Initialization (after Base_Initialize completes)
auto initResult = Log_Initialize();
if (!initResult.IsSuccessful())
{
    // Implement the logic for initialization failure.
    return;
}

// 2) Send an event log
StovePCLogSendParam param;
// All fields are optional, so fill in only the values you need for your game.
param.SetGameVersion(L"1.0.0");
param.SetServerCd(L"Server01");
param.SetContents(L"{\"level\":42,\"class\":\"warrior\"}");

Log_Send(&param, [](CallbackResult callbackResult)
{
    if (callbackResult.GetResult().IsSuccessful())
    {
        // Implement the logic for a successful send.
    }
    else
    {
        // Implement the failure logic (retry/logging, etc.).
    }
});

// 3) Cleanup on exit
Log_UnInitialize();
// Then call Base_UnInitialize

Frequently Asked Questions



Q1. What happens if I call initialization multiple times?
A. Calls after the first are ignored and no error occurs. We recommend calling initialization only once within the app lifecycle.
Q2. How are events that occur while offline handled?
A. The SDK stores events in an internal queue and automatically resends them when the network recovers.
The maximum number of storable events is 1,000; when exceeded, the oldest events are deleted first.
Q3. Can I change an event name later?
A. If you change an event name, previously collected data and new data are aggregated as different events.
To maintain analysis continuity, we strongly recommend finalizing event names at initial design and not changing them afterward.
Q4. Can I prevent real data from accumulating in the analytics system during development?
A. Enabling debug mode in the initialization options means events aren't sent to the real collection pipeline and are only output as local logs.
Be sure to disable debug mode in release builds.
Q5. Can I check whether an event was sent successfully in real time?
A. Passing a callback when calling logEvent() lets you check the send result of individual events.
However, considering battery and performance, we recommend not attaching a callback to every event in production.
Q6. When should I set user attributes?
A. Call it right after login completes or at the moment attribute values change (level-up, tier change, etc.).
Since set attributes are automatically included in all subsequently sent events, we recommend setting them before sending events.
Q7. The log callback isn't called in the PC SDK.
A. The PC SDK's asynchronous API callbacks run on the thread that calls Base_RunCallback().
Please check whether you're calling Base_RunCallback() periodically in the game loop.



Need to contact us directly? stove.developers@smilegate.com