---
source_url: https://www.pubnub.com/docs/sdks/go/logging
title: Logging for Go SDK
updated_at: 2026-05-21T15:46:37.494Z
sdk_name: PubNub Go SDK
sdk_version: v8.1.0
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Logging for Go SDK

PubNub Go SDK, use the latest version: v8.1.0

Install:

```bash
go get github.com/pubnub/go/v8@v8.1.0
```

This page explains how to configure logging in the PubNub Go Software Development Kit (SDK). Logging helps you monitor SDK activity, troubleshoot issues, and maintain audit trails during development and production.

For general logging concepts and best practices applicable to all PubNub SDKs, see [Logging](https://www.pubnub.com/docs/general/setup/logging).

## Logging architecture

The Go SDK provides a flexible logging system with the following features:

* Structured logging: Log entries include typed content for different contexts (simple messages, network requests/responses, errors, user input).
* Custom loggers: Implement the `PNLogger` interface to route logs to external monitoring services, databases, or analytics platforms.
* Multiple logger support: Register multiple loggers simultaneously. All loggers receive the same log entries.
* Built-in default logger: The SDK includes a `DefaultLogger` that outputs formatted logs to console or any `io.Writer`.
* Per-logger log levels: Each logger can set its own minimum log level threshold.

Logging is disabled by default to optimize performance in production environments.

## Log levels

The SDK uses standard log levels to control the amount of detail captured:

| Level | Purpose |
| --- | --- |
| `PNLogLevelTrace` | Internal operations including detailed execution flow, method calls, and state transitions. |
| `PNLogLevelDebug` | User inputs, API (Application Programming Interface) parameters, HTTP (Hypertext Transfer Protocol) requests and responses, and operation results. |
| `PNLogLevelInfo` | Significant events including successful initialization, SDK version, and configuration summary. |
| `PNLogLevelWarn` | Configuration validation warnings, deprecations, and non-breaking issues. |
| `PNLogLevelError` | Errors, exceptions, and failed operations. |
| `PNLogLevelNone` | Logging disabled. |

Each level automatically includes messages from all higher severity levels. The hierarchy is: `ERROR` → `WARN` → `INFO` → `DEBUG` → `TRACE`.

:::warning Logging sensitive information
The `PNLogLevelDebug` and `PNLogLevelTrace` settings may log sensitive information including API (Application Programming Interface) keys, user identifiers, and message content. Use these levels only in development environments. Never enable `DEBUG` or `TRACE` logging in production environments with sensitive data.
:::

## Enable logging

Configure logging when creating your PubNub client by adding loggers to the `Loggers` slice in the configuration.

### Use the default logger

The SDK provides a `DefaultLogger` that outputs to console:

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"os"

	pubnub "github.com/pubnub/go/v8"
)

// Example_loggingSimple demonstrates how to enable simple console logging in the PubNub Go SDK
func Example_loggingSimple() {
	// Create a new PubNub configuration
	config := pubnub.NewConfigWithUserId(pubnub.UserId("loggingDemoUser"))

	// Set the subscribe and publish keys
	// Replace "demo" with your actual keys from the PubNub Admin Portal
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	// Create a simple console logger with INFO level (shows Info, Warn, Error)
	// Logs will be written to stdout with timestamps
	simpleLogger := pubnub.NewDefaultLogger(pubnub.PNLogLevelInfo)

	// Add the logger to the config
	config.Loggers = []pubnub.PNLogger{simpleLogger}

	// Initialize PubNub with the configured settings
	pn := pubnub.NewPubNub(config)

	// Perform operations - they will be logged to console
	_, _, err := pn.Time().Execute()
	if err != nil {
		fmt.Println("Error fetching time:", err)
	} else {
		fmt.Println("Time fetched successfully")
	}

	// Publish a message to demonstrate logging
	_, status, err := pn.Publish().
		Channel("logging-demo-channel").
		Message("Hello from Logging Example").
		Execute()

	if err != nil {
		fmt.Printf("Error publishing message: %v\n", err)
	} else {
		fmt.Printf("Publish status: %d\n", status.StatusCode)
		fmt.Println("Check console output for detailed logging information")
	}
}
```

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

* SDK version and Go runtime information
* User ID and subscribe key
* Publish key (if set)
* Configuration parameters (sensitive fields like `SecretKey` and `CipherKey` are masked with `***`)
* Number of registered loggers

### Write logs to a file

Use `NewDefaultLoggerWithWriter` to direct logs to a file:

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"os"

	pubnub "github.com/pubnub/go/v8"
)

// Example_loggingToFile demonstrates how to log PubNub operations to a file
func Example_loggingToFile() {
	// Create a new PubNub configuration
	config := pubnub.NewConfigWithUserId(pubnub.UserId("loggingDemoUser"))

	// Set the subscribe and publish keys
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	// Specify log file name
	logfileName := "pubnubMessaging.log"

	// snippet.hide
	defer os.Remove(logfileName)
	// snippet.show

	// Open log file, creating it if needed with append mode
	f, err := os.OpenFile(logfileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		fmt.Println("Error opening log file:", err.Error())
		fmt.Println("Logging disabled")
		return
	}

	// snippet.hide
	defer f.Close()
	// snippet.show

	fmt.Println("Logging enabled, writing to", logfileName)

	// Create a logger that writes to the file with DEBUG level
	// This will log Debug, Info, Warn, and Error messages
	fileLogger := pubnub.NewDefaultLoggerWithWriter(pubnub.PNLogLevelDebug, f)

	// Add the logger to the config
	config.Loggers = []pubnub.PNLogger{fileLogger}

	// Initialize PubNub with the configured settings
	pn := pubnub.NewPubNub(config)

	// Perform operations - they will be logged to the file
	_, _, err = pn.Time().Execute()
	if err != nil {
		fmt.Println("Error fetching time:", err)
	} else {
		fmt.Println("Time fetched successfully, check the log file for details")
	}

	// Publish a message to demonstrate logging
	_, status, err := pn.Publish().
		Channel("logging-demo-channel").
		Message("Hello from File Logging Example").
		Execute()

	if err != nil {
		fmt.Printf("Error publishing message: %v\n", err)
	} else {
		fmt.Printf("Publish status: %d\n", status.StatusCode)
		fmt.Println("Check the log file for detailed logging information")
	}

	fmt.Println("Example complete. Logging information has been saved to", logfileName)
}
```

:::note Backward compatibility with log.Logger
The SDK maintains backward compatibility with the deprecated `Log *log.Logger` field. When you set `config.Log`, the SDK automatically creates a `DefaultLogger` with `PNLogLevelDebug` and bridges it to the new logging system. The `Log` field will be removed in a future major version. Use the `Loggers []PNLogger` field for enhanced logging capabilities.
:::

## Logged information

The SDK logs information at various stages of operation.

### SDK initialization

The SDK logs initialization details at the `INFO` level, including:

* PubNub Go SDK version
* Go runtime version and platform (operating system (OS) and architecture)
* Complete configuration with sensitive fields masked

Example log:

```text
02/01/2024 14:23:45.123 PubNub-a1b2c3d4 Info PubNub Go SDK v8.0.0 initialized
Go: go1.21.0 darwin/arm64
Config{
  PublishKey: demo
  SubscribeKey: demo
  SecretKey: ***
  ...
}
```

### Configuration validation warnings

The SDK logs validation warnings at the `WARN` level during initialization when it detects configuration issues:

```text
02/01/2024 14:23:45.124 PubNub-a1b2c3d4 Warn Config validation: PresenceTimeout value 15 is less than the min recommended value of 20, adjusting to 20
```

### API call parameters

The SDK logs user-provided input data for each API (Application Programming Interface) call at the `DEBUG` level. These logs help identify mismatches between expected and actual parameters.

```text
02/01/2024 14:23:45.234 PubNub-a1b2c3d4 Debug PNPublishOperation with parameters:
  Channel: demo-channel
  Message: Hello World
  Meta: map[sender:user123]
```

### Network requests and responses

The SDK logs complete HTTP (Hypertext Transfer Protocol) transaction information at the `DEBUG` level:

#### Request logs include

* HTTP method (GET, POST, PATCH, DELETE)
* Complete URL with query parameters
* Request headers as key-value pairs
* Request body content (for POST or PATCH requests)
* File location where the request was initiated

#### Response logs include

* HTTP status code
* Response body content
* Request URL for correlation
* File location where the response was received

Example request log:

```text
02/01/2024 14:23:45.235 PubNub-a1b2c3d4 Debug request.go:193 Sending HTTP request POST https://ps.pndsn.com/publish/demo/demo/0/demo-channel/0/%7B%22text%22%3A%22Hello%22%7D with headers: map[Content-Type:application/json] body: {"text":"Hello"}
```

Example response log:

```text
02/01/2024 14:23:45.456 PubNub-a1b2c3d4 Debug request.go:245 Received response with 200 content [1,\"Sent\",\"16891234567890123\"] for request url https://ps.pndsn.com/publish/demo/demo/0/demo-channel/0/%7B%22text%22%3A%22Hello%22%7D
```

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

### Errors and exceptions

The SDK logs errors at the `ERROR` level with contextual information:

* Error description
* Error name or type
* Associated API operation (if applicable)
* File location where the error occurred

Example error log:

```text
02/01/2024 14:23:45.789 PubNub-a1b2c3d4 Error request.go:151 Error CreateRequestFailed in PNPublishOperation: invalid character 'x' looking for beginning of value
```

## Log entry structure

Each log entry includes the following components:

| Component | Description |
| --- | --- |
| Timestamp | Date and time when the SDK created the log entry in format `DD/MM/YYYY HH:MM:SS.mmm`. |
| Instance identifier | Format: `PubNub-{instanceId}` where `instanceId` is an 8-character random alphanumeric string. Use this identifier to filter logs from multiple SDK instances. |
| Log level | The severity level: `Trace`, `Debug`, `Info`, `Warn`, or `Error`. |
| Callsite | Optional. The file name and line number where the log was generated (e.g., `request.go:193`). Included for some debug-level logs and errors. |
| Message | The log content describing the operation or event. |

## Custom loggers

Create custom loggers to route log entries to external monitoring services, databases, or analytics platforms. Custom loggers must implement the `PNLogger` interface.

### PNLogger interface

The `PNLogger` interface defines two methods:

```go
type PNLogger interface {
    // Log outputs a log message
    Log(logMsg LogMessage)
    // GetMinLogLevel returns the minimum log level for this logger
    GetMinLogLevel() PNLogLevel
}
```

### Custom logger example

This example shows a custom logger that outputs structured logs with type-specific information:

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"os"

	pubnub "github.com/pubnub/go/v8"
)

// Example_loggingCustom demonstrates how to create a custom logger implementation

// CustomStructuredLogger is an example implementation of a custom logger
// that outputs structured logs in JSON-like format
type CustomStructuredLogger struct {
	minLevel pubnub.PNLogLevel
}

// Log implements the PNLogger interface
func (l *CustomStructuredLogger) Log(logMessage pubnub.LogMessage) {
	// Only log messages at or above the configured level
	if logMessage.GetLogLevel() < l.minLevel {
		return
	}

	// Output structured log in a custom format
	// In a real implementation, you might output JSON or send to a logging service
	fmt.Printf("[%s] level=%s instance=%s message=%q\n",
		logMessage.GetTimestamp().Format("2006-01-02 15:04:05.000"),
		logMessage.GetLogLevel().String(),
		logMessage.GetInstanceID(),
		logMessage.GetMessage(),
	)

	// Handle specific message types using type assertions
	switch msg := logMessage.(type) {
	case pubnub.ErrorLogMessage:
		// If it's an error message, include error details
		fmt.Printf("  error_name=%s operation=%s error_details=%q\n",
			msg.ErrorName,
			msg.Operation.String(),
			msg.Error.Error(),
		)
	case pubnub.UserInputLogMessage:
		// If it's a user input message, include parameters
		fmt.Printf("  operation=%s user_params=%v\n",
			msg.Operation.String(),
			msg.Parameters,
		)
	case pubnub.NetworkRequestLogMessage:
		// If it's a network request, include HTTP details
		fmt.Printf("  method=%s url=%s\n",
			msg.Method,
			msg.URL,
		)
	}
}

// GetMinLogLevel implements the PNLogger interface
func (l *CustomStructuredLogger) GetMinLogLevel() pubnub.PNLogLevel {
	return l.minLevel
}

func Example_loggingCustom() {
	// Create a new PubNub configuration
	config := pubnub.NewConfigWithUserId(pubnub.UserId("loggingDemoUser"))

	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	// Create an instance of our custom logger
	customLogger := &CustomStructuredLogger{
		minLevel: pubnub.PNLogLevelInfo,
	}

	// Add the custom logger to the config
	config.Loggers = []pubnub.PNLogger{customLogger}

	// Initialize PubNub with the configured settings
	pn := pubnub.NewPubNub(config)

	fmt.Println("Custom structured logger configured")

	// Perform operations
	_, status, err := pn.Publish().
		Channel("logging-demo-channel").
		Message("Hello from custom logger").
		Execute()

	if err != nil {
		fmt.Printf("Error publishing message: %v\n", err)
	} else {
		fmt.Printf("Publish status: %d\n", status.StatusCode)
	}
}
```

### Use multiple loggers

Use the built-in default logger and custom loggers simultaneously:

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"os"

	pubnub "github.com/pubnub/go/v8"
)

// Example_loggingMultiple demonstrates how to use multiple loggers with different log levels
func Example_loggingMultiple() {
	// Create a new PubNub configuration
	config := pubnub.NewConfigWithUserId(pubnub.UserId("loggingDemoUser"))

	// Set the subscribe and publish keys
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	// Create multiple loggers for different purposes

	// 1. Console logger for errors only (production-friendly)
	consoleLogger := pubnub.NewDefaultLogger(pubnub.PNLogLevelError)

	// 2. File logger for detailed debugging
	debugLogFile := "pubnub-debug.log"
	// snippet.hide
	defer os.Remove(debugLogFile)
	// snippet.show

	f, err := os.OpenFile(debugLogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		fmt.Println("Error opening debug log file:", err.Error())
		return
	}
	// snippet.hide
	defer f.Close()
	// snippet.show

	debugLogger := pubnub.NewDefaultLoggerWithWriter(pubnub.PNLogLevelDebug, f)

	// Add both loggers to the config
	// Errors will go to console, all debug info will go to file
	config.Loggers = []pubnub.PNLogger{consoleLogger, debugLogger}

	// Initialize PubNub with the configured settings
	pn := pubnub.NewPubNub(config)

	fmt.Println("Multiple loggers configured:")
	fmt.Println("- Console: ERROR level only")
	fmt.Println("- File: DEBUG level and above")

	// Perform operations
	_, _, err = pn.Time().Execute()
	if err != nil {
		fmt.Println("Error fetching time:", err)
	} else {
		fmt.Println("Time fetched successfully")
	}

	// Publish a message
	_, status, err := pn.Publish().
		Channel("logging-demo-channel").
		Message("Hello with multiple loggers").
		Execute()

	if err != nil {
		fmt.Printf("Error publishing message: %v\n", err)
	} else {
		fmt.Printf("Publish status: %d\n", status.StatusCode)
	}

	fmt.Println("Errors (if any) appear on console, all details in", debugLogFile)
}
```

The SDK sends every log entry that meets each logger's minimum level threshold to all registered loggers. In this example:

* Console logger receives only messages at `ERROR` level
* File logger receives all messages at `DEBUG` level and above

## Logging best practices

### Choose the appropriate log level

| Environment | Recommended Log Level |
| --- | --- |
| Production | `PNLogLevelError` to capture critical issues without performance impact. |
| Staging | `PNLogLevelInfo` to monitor operational events. |
| Development | `PNLogLevelDebug` to investigate issues and verify behavior. |
| Deep troubleshooting | `PNLogLevelTrace` when working with PubNub support on complex issues. |

### Protect sensitive data

Never enable `PNLogLevelDebug` or `PNLogLevelTrace` in production environments that handle sensitive information.

These levels may expose:

* API keys and authentication tokens
* User identifiers and personal information
* Message content and metadata
* Request and response payloads

The SDK automatically masks sensitive configuration fields (`SecretKey`, `CipherKey`) in configuration logs, but `DEBUG` and `TRACE` levels may expose sensitive data in network requests and API parameters.

### Use custom loggers for production

Implement custom loggers that integrate with your monitoring and observability infrastructure. Use multiple loggers to send different log levels to different destinations. For example, send errors and warnings to your monitoring service while logging all information to a file for debugging.

### Optimize logging performance

Minimize logging overhead in production:

* Set minimum log level to `PNLogLevelWarn` or `PNLogLevelError`
* Use custom loggers that buffer and batch log entries
* Avoid expensive operations in custom logger implementations

```go
// Minimal logging for production
config.Loggers = []pubnub.PNLogger{
    pubnub.NewDefaultLogger(pubnub.PNLogLevelError),
}

// Disable logging completely (empty slice)
config.Loggers = []pubnub.PNLogger{}
```

### Provide logs to support

When reporting issues to [PubNub support](https://support.pubnub.com/), include complete logs:

1. Set the log level to `PNLogLevelDebug` or `PNLogLevelTrace`
2. Reproduce the issue
3. Collect logs from initialization through the problem occurrence
4. Include the PubNub SDK version (visible in initialization logs)

## Configuration reference

For complete details on all configuration options, see the [Configuration reference](https://www.pubnub.com/docs/sdks/go/api-reference/configuration).