Request baggage #

Request baggage attaches key-value metadata to the logs and metrics emitted during RPC prcessing. The name is borrowed from OpenTelemetry to signal that the data is non-essential — useful for observability but not meant to be relied on for game features. Effort should be taken to minimize use of request baggage– it increases cardinality across monitoring systems and can overwhelm the network and/or downstream metrics, logging, and telemetry systems.

Enabling request baggage #

Request baggage processing is disabled by default. Enable it on the backend(s) where you want metadata attached:

game:
  core:
    logging:
      requestBaggageEnabled: true
social:
  core:
    logging:
      requestBaggageEnabled: true

DefaultRequestBaggagePlugin #

The plugin registered on every backend by default. It attaches a traceId (a randomly generated Uuid) to inbound requests and propagates it through resulting service-to-service calls, providing a single identifier to correlate log entries across a distributed call path.

MethodBehavior
getForExternalRequestReturns a new baggage map containing a generated traceId.
getForServiceRpcReturns the current baggage unchanged when a traceId is already present; otherwise inserts one. These entries will propagate across service-to-service requests.
getForMetricsReturns an empty map; no entries are attached as metric tags by default.

RequestBaggagePluginWithSessionBaggage #

Extends DefaultRequestBaggagePlugin. Overrides one method to include session-baggage entries automatically, otherwise behaves the same is its base class (including generation of the traceId)

MethodBehavior
getForExternalRequestReturns the inherited traceId plus all entries currently stored in the session’s baggage cache.

For how to populate the session baggage cache, see Session baggage.

Custom plugins #

Extend either provided plugin to customize selected hooks. The example below extends RequestBaggagePluginWithSessionBaggage to add a session-derived displayName to every inbound request and to forward only the buildId entry as a metric tag — extend DefaultRequestBaggagePlugin instead if you don’t want session baggage attached automatically.

import pragma.ExternalRequest
import pragma.logging.MutableRequestBaggage
import pragma.logging.RequestBaggage
import pragma.logging.RequestBaggagePluginWithSessionBaggage
import pragma.session.RpcExecutionContext

//...

class MyRequestBaggagePlugin : RequestBaggagePluginWithSessionBaggage() {

    override fun getForExternalRequest(
        request: ExternalRequest,
        session: RpcExecutionContext,
    ): MutableRequestBaggage {
        val result = super.getForExternalRequest(request, session)
        result["displayName"] = session.activePragmaSession.playerSession.displayName
        return result
    }

    override fun getForMetrics(metricName: String, requestBaggage: RequestBaggage): MutableRequestBaggage {
        val result: MutableRequestBaggage = mutableMapOf()
        requestBaggage["buildId"]?.let { result["buildId"] = it }
        return result
    }
}
Take extra care with getForMetrics — any tag whose value space is unbounded will overwhelm OTel collection. Only use tags whose values come from a small, fixed set (such as an enum).

Register the plugin #

Register the plugin by assigning it to pragmaNode.requestBaggagePlugin inside an AlwaysStartedNodeService.

This plugin is registered in a non-standard manner because it resides within pragma-core, whereas most plugins reside within a Pragma service (which provides first party support for plugins).

import pragma.PragmaNode
import pragma.services.AlwaysStartedNodeService
import pragma.services.PragmaService
import pragma.settings.BackendType

//...

@PragmaService(
    backendTypes = [BackendType.GAME, BackendType.SOCIAL],
)
class MyBaggageSetupService(pragmaNode: PragmaNode) : AlwaysStartedNodeService(pragmaNode) {

    override suspend fun run() {
        pragmaNode.requestBaggagePlugin = MyRequestBaggagePlugin()
    }
}

Plugin output limits #

After a plugin returns entries, the engine validates them against SessionCoreConfig before attaching the result to logs emitted during the RPC. Entries whose key or value exceeds the size limits are dropped and a warning is logged; if the total entry count exceeds baggageEntryLimit, all entries are rejected.

While these config keys also appear on DefaultSessionPluginConfig for session-baggage storage — the two sets of limits are discrete and enforced independently.
SettingDefaultDescription
baggageEntryLimit5Maximum number of entries a plugin may return.
baggageKeySizeLimit36Maximum character length of each key.
baggageValueSizeLimit36Maximum character length of each value.

Example raising the entry cap:

game:
  core:
    sessionCoreConfig:
      baggageEntryLimit: 10
social:
  core:
    sessionCoreConfig:
      baggageEntryLimit: 10
  • Session baggage — a session-scoped key-value cache that RequestBaggagePluginWithSessionBaggage reads to attach per-session context to logs.