For AI agents: this page in Markdown: https://www.pubnub.com/docs/sdks/kotlin/logging.md. Documentation index: https://www.pubnub.com/llms-full.txt.

Logging for Kotlin SDK

This page explains how to configure logging in the PubNub Kotlin Software Development Kit (SDK) using SLF4J and custom loggers.

Logging architecture​

You can configure logging for different environments and use cases:

  • SLF4J integration: All logs route through SLF4J, allowing you to use any SLF4J-compatible backend (logback, log4j, slf4j-simple, commons-logging, java.util.logging)
  • Custom loggers: Optionally add custom logger implementations via the customLoggers configuration parameter to route logs to external systems
  • Structured logging: Logs include structured data with instance IDs, timestamps, log levels, and typed content

The SDK sends all log entries to both SLF4J and any configured custom loggers simultaneously.

Log levels​

SLF4J uses standard log levels:

LevelPurpose
TRACEInternal operations: serialization, encryption, subscription lifecycle, and detailed execution flow
DEBUGUser inputs, API parameters, HTTP requests and responses, and configuration properties
INFOSignificant events like successful initialization and configuration changes
WARNDeprecation warnings, unusual conditions, and non-breaking validation warnings
ERRORErrors, exceptions with stack traces, and failed operations

The SDK logs all configuration properties at DEBUG level during initialization. Sensitive values such as secret keys are masked.

Custom loggers​

Beyond SLF4J, you can implement the CustomLogger interface to route logs to external monitoring services, databases, or analytics platforms alongside your SLF4J backend.

CustomLogger interface​

The CustomLogger interface supports string messages and structured LogMessage objects:

1interface CustomLogger {
2 val name: String get() = "CustomLogger"
3
4 // String-based logging methods
5 fun trace(message: String?)
6 fun debug(message: String?)
7 fun info(message: String?)
8 fun warn(message: String?)
9 fun error(message: String?)
10
11 // Structured logging methods
12 fun trace(logMessage: LogMessage)
13 fun debug(logMessage: LogMessage)
14 fun info(logMessage: LogMessage)
15 fun warn(logMessage: LogMessage)
show all 17 lines

The SDK calls both overloads for each log entry:

  • String version - a simplified, human-readable message
  • LogMessage version - structured data including instance ID, timestamp, location, and typed content

You only need to implement the methods you plan to use. The default implementations do nothing.

Structured logging with LogMessage​

LogMessage provides structured information for each log entry:

FieldDescription
messageThe log content (one of: Text, Object, Error, NetworkRequest, or NetworkResponse)
detailsOptional additional context
typeAutomatically inferred from message content (TEXT, OBJECT, ERROR, NETWORK_REQUEST, NETWORK_RESPONSE)
locationSource class or method generating the log
pubNubIdPubNub instance identifier
logLevelThe SLF4J log level (TRACE, DEBUG, INFO, WARN, ERROR)
timestampWhen the log was created with millisecond precision (format: HH:mm:ss.SSS)

Custom logger example​

1

Configure the SDK with your custom logger:

1

Enable logging​

Logging is automatically enabled when you create a PubNub instance. The SDK logs configuration details at the DEBUG level during initialization. SLF4J routes all logs to your configured backend.

1

The SDK automatically logs the complete configuration at initialization, including:

  • User ID and subscribe key
  • Publish key (if set)
  • Secret key status (partially masked as first 8 characters plus length, for example a1b2c3d4… (len=44), if configured)
  • Connection timeouts and retry settings
  • Presence and heartbeat configuration
  • Custom logger count (if configured)
  • Instance identifier
Secret keys are only partially masked

The one-time configuration log at initialization shows only the first 8 characters and total length of the secret key and auth token (for example, a1b2c3d4… (len=44)), not a full mask. These same values are not masked at all in network request and response logs. See Protect sensitive data.

Logged information​

The Kotlin SDK logs information at various stages of operation. This provides complete visibility into SDK behavior.

Configuration at initialization​

When you create a PubNub instance, the SDK logs all configuration properties at the DEBUG level. The SDK also logs any subsequent changes to these properties.

Each configuration log entry includes:

  • Instance identifier (unique ID)
  • SDK version information
  • All configuration property names and values
  • Masked sensitive values (secret keys, authentication tokens)

API call parameters​

The SDK logs user-provided input data for each API call at the DEBUG level.

Logged parameters include:

  • Channel names and channel groups
  • Messages and metadata
  • Timetoken values
  • Filter expressions
  • Custom query parameters
  • Operation-specific parameters

These logs help identify mismatches. You can compare expected input with actual data passed to endpoints.

Network requests and responses​

The SDK logs complete HTTP transaction information at the DEBUG level:

Request logs include​

  • HTTP method (GET, POST, PUT, PATCH, DELETE)
  • Complete URL with origin and path
  • Query parameters as key-value pairs
  • Request headers
  • Request body content (for POST, PUT, or PATCH requests), for JSON and text bodies that fit within loggedHttpResponseMaxBytes. Other bodies are described by size and content type only.
  • Request identifier (if configured)

Response logs include​

  • HTTP status code
  • Response headers
  • Response body content (JSON and text bodies as text, including vendor types that end in +json, such as the DataSync responses. Other bodies are Base64-encoded.)
  • Request URL for correlation
  • Negotiated protocol (protocol field, for example h2 or http/1.1)

Network logs help troubleshoot connectivity issues. Network logs also show exactly what data flows between your application and PubNub servers.

HTTP/2 negotiation logging​

Each response log's JSON payload includes a protocol field showing the protocol OkHttp negotiated for that request:

1{
2 "protocol": "h2"
3}

If HTTP/2 wasn't negotiated, protocol is http/1.1 instead. For configuration details, refer to HTTP/2.

Errors and exceptions​

The SDK logs errors and exceptions at the ERROR level with:

  • Error type (exception class name)
  • Error message
  • Stack trace (up to 10 frames)
  • Duration before failure (for network errors)
  • Request details for failed operations

Log content configuration​

LogContentConfig controls how much content the SDK renders into each debug log record. It doesn't affect the log source, level, or format. Your SLF4J backend or CustomLogger implementation does that.

Configure it via the logContentConfig property on PNConfiguration.Builder:

1

LogContentConfig properties​

PropertyDescription
loggedMessageContentMaxBytes
Type: Int
Default:
500
Maximum UTF-8 byte length of message content rendered in publish, signal, and subscribe debug log entries. Set to 0 to replace the content field with [...]. Set to Int.MAX_VALUE for no limit. Negative values are treated as 0.
loggedHttpResponseMaxBytes
Type: Int
Default:
2000
Maximum byte length of the HTTP body included in network debug log entries. For a response, longer bodies are truncated. For a request, only JSON and text bodies up to this length are logged, and longer ones are described by size and content type. Set to 0 to replace the response body field with [...]. Set to Int.MAX_VALUE for no limit. Negative values are treated as 0.

Suppress all message content in logs​

Set loggedMessageContentMaxBytes to 0 to prevent any message content from appearing in debug logs. The SDK replaces the content field with [...] while still logging the message fingerprint (pn_mfp) and total byte count.

1

Raise the response body cap for troubleshooting​

When large API responses are truncated in your logs, raise loggedHttpResponseMaxBytes to capture the full body.

1

Production recommendations

The default caps (500 bytes for message content, 2000 bytes for HTTP responses) are intentional. Raising them significantly in production increases log volume. Avoid setting either property to Int.MAX_VALUE in production unless you control log storage costs.

SLF4J backend configuration​

The following sections explain how to configure different SLF4J backends. Choose the backend that best fits your environment and logging requirements.

For more information about configuration parameters, refer to Configuration.

Implement logging on Android​

Add the following dependency to the project and configure it.

Example configuration:

1

The logs will appear in Logcat.

Implement logging using log4j​

To implement logging using log4j you need to add the following references to the project. Using log4j you can log to console or a file or both.

  • log4j-slf4j2 file which acts as a bridge between slf4j and log4j.
  • log4j-api file, which provides the underlying logging framework API.
  • log4j-core file, which provides the underlying logging framework Implementation.
1

See this example:

1

Implement logging using slf4j-simple​

To implement logging using slf4j-simple you need to add the following references to the project.

Along with these references you need to add the simplelogger.properties file in the CLASSPATH.

See this example:

1

Example usage of slf4j-simple​

1

Implement logging using logback-classic​

To implement logging using logback, you need to add the following references to the project.

See an sample logback.xml logback config file:

1

See this example:

1

Implement logging using java.util.logging​

To implement logging using java.util.logging you need to add the following references to the project.

JVM runtime provides the underlying logging framework.

Implement logging using commons-logging​

To implement logging using commons-logging you need to add the following references to the project.

The underlying logging framework is chosen dynamically by commons-logging.

No logging​

To implement no logging you have two options:

Logging best practices​

Use these recommendations for effective logging.

Choose the right log level for your backend​

EnvironmentRecommended SLF4J Level
ProductionWARN or ERROR to capture issues without performance impact.
StagingINFO to monitor operational events.
DevelopmentDEBUG when actively developing or investigating issues.
Deep troubleshootingTRACE only when working with PubNub support on complex issues.

Configure your SLF4J backend (log4j, logback, etc.) to set the appropriate level for the com.pubnub logger:

<!-- Example logback.xml configuration -->
<logger name="com.pubnub" level="INFO" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>

Protect sensitive data​

Never enable DEBUG or TRACE logging in production environments that handle sensitive information.

These levels may expose:

  • API keys (publish and subscribe keys are visible in requests)
  • User identifiers
  • Message content
  • Authentication tokens (only partially masked in configuration logs, but logged unmasked in network requests)
  • Complete request URLs, including Access Manager signature and auth token query parameters used for signed requests
  • The full token string returned by grantToken calls, since response bodies are logged in full at DEBUG (up to loggedHttpResponseMaxBytes)

Use custom loggers for monitoring​

Implement CustomLogger to route critical errors and metrics to external monitoring services without affecting SLF4J logging:

val configuration = PNConfiguration.builder(UserId("uniqueUserId"), "demo").apply {
publishKey = "demo"
customLoggers = listOf(
MonitoringLogger(), // Send errors to monitoring service
MetricsLogger() // Track usage patterns
)
}.build()

Custom loggers receive structured LogMessage objects that are easier to parse than string-based logs.

Monitor log volume​

TRACE and DEBUG levels generate significant output. Ensure your logging infrastructure can handle the volume. This is especially important in high-throughput applications.

Network request and response logging at DEBUG level can be particularly verbose for applications with many API calls.

Optimize performance in production​

Set your SLF4J backend to WARN or ERROR level for the com.pubnub logger. This optimizes performance and reduces storage costs:

<!-- Production logback.xml configuration -->
<logger name="com.pubnub" level="WARN" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>

Android-specific recommendations​

For Android applications, use SLF4J Android to optimize logging for mobile devices:

  • Set log level to WARN or ERROR in release builds
  • Consider disabling network request/response logging in production to reduce logcat noise
  • Use custom loggers to send critical errors to crash reporting services like Firebase Crashlytics

Provide complete logs to support​

When reporting issues to PubNub support, provide complete logs:

  1. Set your SLF4J backend to DEBUG or TRACE level for com.pubnub
  2. Reproduce the issue
  3. Collect logs from SDK initialization through the problem occurrence
  4. Include the PubNub SDK version and Kotlin version

The configuration is automatically logged at initialization, which helps support diagnose issues faster.

Was this page useful?

Last updated on