Цю сторінку ще не перекладено — показано англійську версію.
Analytics
Усе, що треба порахувати потім, а не побачити зараз. Оголосіть типізовану подію телеметрії, надішліть її — і вона ляже поруч із подіями самої платформи: пройдений рівень, крок воронки, економічна подія, тривалість сесії, відвал на навчанні. Цей модуль лише надсилає: сам він нічого не читає, не агрегує й нікуди не доставляє. Куди піде пакет подій, вирішує маршрутизатор у Extensibility.
Коли це потрібно
- Щось треба порахувати потім: крок воронки, пройдений рівень, економічну подію, тривалість сесії.
- Порівняння має переживати нові збірки гри: тип несе версію схеми (schema), тож воронка, якій уже рік, не змішує мовчки два значення одного поля.
- Обсяг великий, і втрата рядка прийнятна, якщо ви так оголосили: телеметрія — єдине місце в контракті, де оголошена втрата законна.
- Не знадобиться, якщо хтось має відреагувати. У події (event) телеметрії взагалі немає підписників, а факт, про який мають дізнатися інші, — це ігрова подія.
Хто що робить
| Актор | Може | Не може |
|---|---|---|
будь-який актор | оголошувати типи в схемі; надсилати події від власного імені — по одній або пакетом (batch); читати оголошені типи | заповнювати контекст; читати, запитувати чи агрегувати надіслане |
backend-service | те саме, а також надсилати події від імені гравця через делегування | читати телеметрію: дозволу на читання немає, бо немає й операції читання |
Коротко
BossDefeated: іменовані типізовані поля замість JSON-блоба[Event("boss_defeated")]
public class BossDefeated
{
public string BossId = "";
public int PartySize;
public float FightSeconds;
}
PlayServ.Analytics.Emit(new BossDefeated { BossId = "hydra", PartySize = 4, FightSeconds = 212f });@Event('boss_defeated')
export class BossDefeated {
bossId = '';
partySize = 0;
fightSeconds = 0;
}
PlayServ.analytics.emit(new BossDefeated({ bossId: 'hydra', partySize: 4, fightSeconds: 212 }));@event("boss_defeated")
class BossDefeated:
boss_id: str = ""
party_size: int = 0
fight_seconds: float = 0.0
playserv.analytics.emit(BossDefeated(boss_id="hydra", party_size=4, fight_seconds=212.0))Як оголо шувати через атрибути в Go, поки не вирішено (O-1). Приклади з’являться, коли оберуть спосіб запису.
USTRUCT(PSEvent = (Name = "boss_defeated"))
struct FBossDefeated
{
GENERATED_BODY()
UPROPERTY() FString BossId;
UPROPERTY() int32 PartySize;
UPROPERTY() float FightSeconds;
};
// declarations compile into the same pushed model — playserv push from the UE project or CI
// the declared type becomes a generated member under the Emit node
Client->Analytics->Emit->BossDefeated({ TEXT("hydra"), /*PartySize*/ 4, /*FightSeconds*/ 212.f });
// co_await support ships later: a built-in SDK coroutine wrapper that respects Unreal's GC and threading.[Event("boss_defeated")]
public class BossDefeated
{
public string BossId = "";
public int PartySize;
public float FightSeconds;
}
PlayServ.Analytics.Emit(new BossDefeated { BossId = "hydra", PartySize = 4, FightSeconds = 212f });Визначення — це схема, тож те, що надходить, має іменовані типізовані поля, а не JSON-блоб. Його оголошують як окремий вид, а не як ігрову подію з прапорцем.
Модель
Що оголошує тип події телеметрії.
| Оголошення | Що це |
|---|---|
name | власне ім’я типу |
fields | типізовані системою типів платформи; маска полів (field mask) застосовується до них так само, як і скрізь |
версія схеми | обов’язкова й не виводиться з версії SDK. Воронка порівнює події, зібрані в різних збірках гри, і без версії таке порівняння мовчки змішує непорівнюване |
sampling | яка частка подій цього типу проходить далі. Семплювання оголошують на типі, а реалізація ніколи не обирає його сама залежно від навантаження: якби частка змінювалася сама собою, воронки за різні дні стали б непорівнюваними |
допустимість втрат | чи допускає цей тип втрати |
поведінка під час видалення | як видалення гравця позначається на цьому типі — видаленням або анонімізацією. Політику оголошує студія, а виконує модуль |
Що справджується для кожної події телеметрії.
| Завжди | Що це |
|---|---|
немає адресата | ні отримувача, ні групи, ні підписки. Якщо хочеться когось адресувати, це ознака, що потрібна ігрова подія |
контекст | належить платформі: вона додає актора або позначку анонімності, сесію, середовище, версію збірки й момент за оголош еним годинником. Викликач не може його заповнити: якщо він підставить актора чи версію збірки, платформа все одно запише власні значення замість переданих |
частка семплювання | передається разом із подією: без неї абсолютне число не відновити з того, що надійшло |
втрата | помітна в сукупності: частка недоставленого за період доступна споживачеві. Помітності кожної окремої втрати не обіцяють, бо за обсягів телеметрії повідомлення про кожну втрату саме стало б потоком даних |
надсилання | не ідемпотентне: два виклики — це два факти, і ключа ідемпотентності воно не приймає, бо придушення другого виклику втратило б дані. Дізнатися результат загубленого надсилання неможливо, і це й не потрібно: допустимість втрат оголошують заздалегідь, одразу для всіх викликів |
події | і є історією: власної модуль не зберігає |
Помилки
- Неоголошений тип і поле, що не відповідає схемі типу, — це відмови вал ідації. Жодна з них не стане несподіванкою під час виконання, бо тип потрапляє в адмін-консоль зі свого оголошення.
- Завелика подія — відмова валідації; поля ніколи мовчки не обрізають.
- Перевищено частоту — відповідь категорії обмеження частоти з часом, до якого повторювати марно.
- Відкидання під час семплювання — не помилка, як і допустима втрата. Виклик виконано, а відкидання — оголошена поведінка. Якби про них повідомляли як про збій, оголошену поведінку не можна було б відрізнити від несправності.
- Пакет обробляють або цілком, або поелементно, і це оголошено — ніколи не «як вийшло».
Обмеження
Конкретні числа з’являться в розділі про ліміти платформи, а що відбувається на кожній межі, визначено вже зараз.
- Частота подій на актора: відмова через обмеження частоти з указаним терміном. Перевищення частоти ніколи не означає тихого відкидання: це або така відмова, або оголошене відкидання під час семплювання.
- Розмір однієї події: відмова валідації, а не мовчки обрізані поля.
- Розмір пакета: пакет відхиляють ще до надсилання, а не застосовують частково.
- Оголошені типи на проєкт: нове оголошення відхиляють під час деплою, а не під час виконання.
- Поля в типі: так само, під час деплою.
- Строк зберігання: після оголошеного строку подія вже недоступна.