Telemetry #

The Telemetry service accepts events from game clients, game services, Pragma Engine plugins, and custom services.

The service accepts events in realtime and delegates to a configured storage provider. Studios can use standard, existing toolchains for data analytics and processing.

Data can be passed individually or in a batch, and messages are sent as JSON. Several standard fields are provided outside of the JSON payload to help with grouping, filtering, and aggregating events.

Anatomy of an Event #

Event Sources #

The sourceId represents the source of an event, such as a player game client, or game server.

  • Player events: Set by the platform from the player session.
  • Trusted source events: Supplied by the caller (Partner, Operator, or Service gateways).
  • Batch events: Caller specifies a sourceID for each event, enabling a game server to send events on behalf of all players in a game in a single batch.

Request Types #

Player event request

For events requested by a player.

{
  "event": {
    "name" : "player-open-menu",
    "json" : "{\n  \"menuClicked\": \"shopkeeper\",\n  \"durationMenuOpenSeconds\": 43,\n  \"interactionsInMenu\": 7\n, \"transactions\": 2\n}"
  }
}

Partner event request from a game server

For events from a game server.

{
  "sourceId": "game-server-1",
  "event": {
    "name": "boss-defeated",
    "json": "{\n  \"boss_id\": \"miniboss_1\",\n  \"damage_dealt\": 2200,\n  \"encounter_duration_sec\": 17\n}"
  }
}

Stored event

For recorded events.

{
  "name": "player-open-menu",
  "timestamp_millis" : 1646097667207,
  "id_hash": 3241420594091297482,
  "event_json": "{\n  \"menuClicked\": \"shopkeeper\",\n  \"durationMenuOpenSeconds\": 43,\n  \"interactionsInMenu\": 7\n, \"transactions\": 2\n}"
}

Understanding the Telemetry Plugin #

The Telemetry plugin allows users to persist events to a datastore of choice, either by configuring the implementations provided by the engine or by building a custom plugin implementation.

interface TelemetryPlugin {

    suspend fun recordEvent(event: Event)

    suspend fun recordEvents(events: List<Event>)

    suspend fun getEvents(): List<Event>
}

Operationalizing Telemetry #

The Telemetry service is responsible for terminating events to the configured data store as quickly as possible. Once persisted, developers are encouraged to build workflows to operationalize the data.

For example, exploratory queries and ad-hoc reports can be built against raw telemetry, but it is adviseable to transform raw events into well-formed schemas that are tailored to their purpose. This improves performance, relaibility, and reduces the cost and complexity of producing actionable insights.

Similarly, while it’s possible to build reports and dashboards against raw telemetry data, it’s not recommended. The result will be dashboards that are slow to load due to the volume of data being processed. The reports will also be fragile, breaking when changes are made to the raw telemetry events. Instead, create ETLs that aggregate data into an operable format and build reports against these.

Sample game health report workflow #

Below is a sample workflow for building a game health report.

sequenceDiagram participant o as Operator participant gs as GameServer participant t as Telemetry participant db as Database participant s as ScheduledJob participant d as Dashboard gs->>t:events t->>db:store(events) s->>db:runEtl(gameHealth) db->>db:writeToGameHealthTable() o->>d:viewGameHealthDashboard() d->>db:retrieveGameHealthReport()