- 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 callingAuth.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
- Secure the external identifier: prepare the external-identifier value issued by the game/service. (e.g., an MMP user ID)
- Call
Log.setExternalId(externalId): set the identifier before callingAuth.initialize(). - 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
| Situation | Cause | Solution |
|---|---|---|
| Some early logs are missing the external identifier | You 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 truncated | It 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
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. CallingLog_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 withBase_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
- Initialization: You can send logs only after initializing the LogSDK (
Log_Initialize()) once BaseSDK initialization (Base_Initialize()) completes. - Log transmission: Set metadata such as game version and server code, plus additional data (a
contentsJSON string), in the log-item parameter (StovePCLogSendParam), and send the log (Log_Send()). - Result handling: Verify success via the result object in the callback. On failure, branch by error code.
- Cleanup: Right before the game exits, clean up the LogSDK with
Log_UnInitialize(), then clean up BaseSDK withBase_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
| Situation | Cause | Solution |
|---|---|---|
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 returned | You 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 returned | It 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 called | If 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
// 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(¶m, [](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