Skip to content

Send event logs

Call CollectClientLogAsync() to send events that occur in the app to Analytics. Before you call it, create a log event for each event and put them in a single list.

1. Prepare log events

A log event is data that records a single event that occurred in the app, and it is the unit that Analytics collects and analyzes. A single log event contains an event name, an event time, and attributes that the app defines.

Create log events as ClientLogEvent objects and put them in the LogBody list of ClientLogCollectRequest. All log events in the list are sent in a single request. Even if LogBody is empty, the SDK sends the request as is, so include at least one log event when you call it. Prepare each field of ClientLogEvent as follows.

1.1. EventName

In EventName, put the event name as a string that indicates which event occurred. This value is required for every log event. The app defines the name. For example, for a log event you send when the user's level goes up, use a name such as levelup_log.

1.2. EventTime

In EventTime, put the time when the event occurred as a DateTimeOffset value. This value is required for every log event. Get the current time with DateTimeOffset.Now when the event occurs and put it in. Even if you collect log events and send them later, you must put the event time, not the sending time.

The SDK converts EventTime into an RFC 3339 string, the internet standard format for dates and times, and sends it. This string also includes the offset from Coordinated Universal Time (UTC). If you do not specify EventTime, the SDK does not treat it as an error and sends the default value of DateTimeOffset as is, so you must specify it yourself. The following are examples of the string sent for each EventTime value.

  • 7:34:42 AM on January 1, 2026, Korea time: 2026-01-01T07:34:42.0000000+09:00
  • When not specified: 0001-01-01T00:00:00.0000000+00:00

1.3. DeviceId

In DeviceId, you must put exactly the same value as the DeviceKey that the app puts in login requests. This is because data can be analyzed accurately only when the device that sent the log event matches the device used for authentication.

DeviceKey is the device identification value that goes into login requests regardless of the account type, such as guest, username, external authentication provider, or custom account. The SDK does not fill in DeviceId automatically and does not save DeviceKey. Have the app put in the value itself in the following order.

  1. Load the DeviceKey that the app created and saved on the device. DeviceKey is a value created and saved once when the app is first launched, so it is already on the device even before login. For how to create and store it, see deviceKey.
  2. Put the loaded value in DeviceId as is. Put the same value in every log event, both before and after login, and do not create a new value for DeviceId.

1.4. UserId

UserId is an optional field that holds the user identifier. If you do not set it, the log event is sent without this field.

1.5. IdentifierProvider

IdentifierProvider is an optional field that indicates the identifier provider. The server always overwrites it with hive, so do not specify it.

1.6. Event attributes

Add information needed for analysis other than the event name and event time to AdditionalProperties as event attributes. The server collects the attributes without interpreting their contents, so you do not need to define attributes in advance. The app decides their names and number and sends them.

AdditionalProperties is a dictionary that holds attribute names as keys and attribute values as values. The SDK builds the request body in JSON, a data interchange format, and sends it. Each attribute is recorded as a field at the same level as the event name. The default value is an empty dictionary, and if it is empty, no attributes are sent.

1.6.1. Attribute value format

For attribute values, put the JSON value itself as a string, not text to display on screen. For example, a string value must include its double quotes.

Value type Value in C# code JSON sent
Number "42" 42
String "\"gold\"" "gold"
Boolean "true" true
Array "[1,2]" [1,2]
Object "{\"a\":1}" {"a":1}
JSON null "null" null
C# null null null
Warning

The SDK does not validate attribute values and writes them to the request body as is. If even one value is not a valid JSON value, such as putting the string value gold as "gold" instead of "\"gold\"", the entire request body becomes invalid JSON. Other log events in the same request are also sent in the invalid body.

1.6.2. Attribute names to avoid

eventTime, eventName, deviceId, userId, and identifierProvider are the names used to send the fields of ClientLogEvent. If you use these names as attribute names, a field with the same name can be sent twice in one log event, so do not use them.

For details about event attributes, see Send event attributes in the Hive Console.

2. Send event logs

Method

CollectClientLogAsync

Call CollectClientLogAsync() to send the prepared list of log events. When the server collects the logs, it returns Success, and there is no response data. The SDK automatically sends the App ID you specified during initialization with every request, so you do not need to put it in the request.

Send before and after login

Call CollectClientLogAsync() the same way both before and after the user logs in. Login is not a requirement for using Analytics, so events that occur before login, such as right after the app launches, are also sent. The only thing that differs depending on login status is the authentication information that the SDK includes in the request.

  • Before login: The request is sent without an authentication token
  • After the login session is activated: The session's authentication token is automatically included in the request

When a login session is active, the server identifies the user who sent the logs from the authentication token in the request. The SDK adds the authentication token, so the app does not need to put it in the request itself.

Call parameters

Field name Type Required Description
request ClientLogCollectRequest Required The request that holds the list of log events to send
context ApiCallContext? Optional Per-call settings object. If omitted, the default values are used.

If you pass null to request, an ArgumentNullException is thrown.

ClientLogCollectRequest

Field name Type Required Description
LogBody IReadOnlyList<ClientLogEvent> Required List of log events to send. The default value is an empty list, and the request is sent as is even if it is empty. Do not put null

ClientLogEvent

Field name Type Required Description
EventTime DateTimeOffset Required Time when the event occurred. If not specified, the default value of DateTimeOffset is sent, so always specify it
EventName string Required Event name that the app defines. Example: levelup_log
DeviceId string? Optional Device identifier. Put the same value as the DeviceKey used for login. For details, see DeviceId.
UserId string? Optional User identifier
IdentifierProvider ClientLogEventIdentifierProvider? Optional Identifier provider. The server always overwrites it with hive, so do not specify it
AdditionalProperties IDictionary<string, string> Optional Event attributes whose names the app defines. Values are strings that represent JSON values. For the rules, see Event attributes.

Call example

Check the Success, Failure, and UnknownOutcome results of AnalyticsCollectClientLogResult in the following example and in the response status. For the result model and handling principles of the common failure (Failure) returned when the request cannot be performed, see Common error handling.

The following example creates and sends one log event when the user's level goes up. In the example, deviceKey is a variable that holds the DeviceKey value the app created and saved on the device.

using System;
using System.Collections.Generic;
using Hive.Axyl.Analytics;
using Hive.Axyl.Core;
using UnityEngine;

IAnalyticsService analytics = HiveCore.Resolve<IAnalyticsService>();

var request = new ClientLogCollectRequest
{
    LogBody = new[]
    {
        new ClientLogEvent
        {
            EventTime = DateTimeOffset.Now,   // Time when the event occurred
            EventName = "levelup_log",
            DeviceId  = deviceKey,            // Same value as the DeviceKey used for login
            AdditionalProperties = new Dictionary<string, string>
            {
                ["level"]        = "12",              // Number
                ["stage"]        = "\"boss_room\"",   // For strings, include the double quotes.
                ["isFirstClear"] = "true",            // Boolean
            },
        },
    },
};

AnalyticsCollectClientLogResult result = await analytics.CollectClientLogAsync(request);

switch (result)
{
    case AnalyticsCollectClientLogResult.Success:
        // The server collected the logs. There is no response data.
        break;

    // Handle common failures (network errors, call cancellation, server errors, and so on)
    case AnalyticsCollectClientLogResult.Failure failure:
        HiveError err = failure.Problem;
        Debug.LogError($"[{err.Code}/{err.ExternalCode}] {err.Message}");
        break;

    // Treat results that this SDK version does not define as failures and record the result code.
    case AnalyticsCollectClientLogResult.UnknownOutcome unknownOutcome:
        Debug.LogWarning($"Unknown result: {unknownOutcome.Code} {unknownOutcome.RawJson}");
        break;

    default:
        Debug.LogWarning($"Unhandled result: {result.GetType().Name}");
        break;
}

Response data

No data is returned on success. When you receive Success, the server has collected the log events in the request.

Response status

The returned object AnalyticsCollectClientLogResult is one of Success, Failure, or UnknownOutcome. Branch with a switch statement to handle it.

Response case Description App client handling
Success The server collected the logs. There is no response data. No further handling
Failure Common Failure. This includes network errors, call cancellation, server errors, and so on, and you can check the code the server sent in Failure.Problem.ExternalCode. For the meaning of each code, see Common Failure codes by module. For how to handle each cause, see Handling by failure cause.
UnknownOutcome A new result that this SDK version does not recognize. Treat it as a failure and record the result code

Learn more