---
source_url: https://www.pubnub.com/docs/sdks/dart/logging
title: Logging for Dart SDK
updated_at: 2026-05-29T11:10:45.682Z
sdk_name: PubNub Dart SDK
sdk_version: 7.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 Dart SDK

PubNub Dart SDK, use the latest version: 7.1.0

Install:

```bash
dart pub add pubnub@7.1.0
```

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

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 Dart SDK provides a flexible logging system with unique features:

* Instance-level logging: Configure logging globally for a PubNub instance using `LoggingConfiguration`
* Zone-scoped logging: Enable logging for specific code paths using `provideLogger`
* Built-in logger: The SDK includes `StreamLogger` that outputs to streams for flexible consumption
* Custom loggers: Implement the `ILogger` interface to route logs to external monitoring services, databases, or analytics platforms
* Stream-based output: Subscribe to log streams for printing, file writing, or sending to monitoring services
* Runtime log level changes: Adjust verbosity dynamically with `setLogLevel()`

Logging is disabled by default (`Level.off`) to optimize performance in production environments.

## Log levels

The Dart SDK uses a weight-based log level system. `StreamLogger` assigns a weight to each log record. A message is logged if its level is less than or equal to the active `logLevel`. For example, if `logLevel` is set to `Level.warning` (80), messages with level 80 or less will be recorded.

| Level | Weight | Purpose |
| --- | --- | --- |
| `Level.off` | 0 | Logging is disabled. Default setting. |
| `Level.shout` | 10 | Extra debug information. Use only when debugging. |
| `Level.fatal` | 20 | Fatal errors that end in application crash or exit. |
| `Level.severe` | 40 | Severe exceptions that need to be resolved. |
| `Level.warning` | 80 | Warnings and unusual conditions. |
| `Level.info` | 160 | Informational messages about significant events. |
| `Level.verbose` | 320 | Verbose mode for detailed operational information. |
| `Level.fine` | 500 | Fine mode for granular debugging. |
| `Level.silly` | 640 | Super verbose mode for maximum detail. |
| `Level.all` | 10000 | All log levels will be captured. |

For more information, refer to the [Level class](https://pub.dev/documentation/pubnub/latest/pubnub.logging/Level-class.html#static-properties) documentation.

:::warning Logging sensitive information
`Level.all`, `Level.silly`, `Level.fine`, and `Level.verbose` settings may log sensitive information including API keys, user identifiers, and message content. Use these levels only in development environments. Never enable detailed logging in production environments with sensitive data.
:::

## Enable logging at the instance level

Use the `logging` parameter on the `PubNub` constructor with `LoggingConfiguration` to enable and control logging globally for that instance. You can also print to console automatically.

```dart
import 'package:pubnub/pubnub.dart';
import 'package:pubnub/logging.dart';

void main() async {
  final pubnub = PubNub(
    defaultKeyset: Keyset(
      subscribeKey: 'demo', // Replace with your Subscribe Key from the PubNub Admin Portal
      publishKey: 'demo',   // Replace with your Publish Key from the PubNub Admin Portal
      userId: UserId('loggingDemoUser'),
    ),
    logging: LoggingConfiguration(
      logLevel: Level.all,     // Enable all logs
      logToConsole: true,      // Optional: print formatted logs to console automatically
      // loggerName: 'myApp',  // Optional: custom logger name
    ),
  );
}
```

### Change log level at runtime

Adjust the log level dynamically during application execution:

```dart
// Change logging verbosity dynamically later in your app
pubnub.setLogLevel(Level.info);
```

## Enable custom logging

```dart
import 'package:pubnub/pubnub.dart';

class JsonLogger implements ILogger {
  @override
  void log(int level, dynamic message) {
    final logEntry = {
      'timestamp': DateTime.now().toIso8601String(),
      'level': Level.getName(level),
      'message': message.toString(),
      'service': 'pubnub',
    };
     // implement method that communicates with external logging service.
    // sendToLoggingService(jsonEncode(logEntry));
  }

  // Implement other methods...
}

void main() async {
  // Create a custom logger
  var jsonLogger = JsonLogger();

  // Configure PubNub with custom logger
  final pubnub = PubNub(
    defaultKeyset: Keyset(
      subscribeKey: 'demo',
      publishKey: 'demo',
      userId: UserId('custom-logger-example-user'),
    ),
    // Configure logging to use our custom logger that communicates with external service.
    logging: LoggingConfiguration(
      logLevel: Level.all, // Log everything
      customLogger: jsonLogger,
      logToConsole: true, // Also log to console
      logFormat: r'$time [${level.name}] $scope: $message',
    ),
  );

  print('PubNub instance created with custom logger');

  try {
    // Example: Publish a message (this will generate logs)
    print('\nPublishing a test message...');
    final publishResult = await pubnub.publish(
      'test-channel',
      'Hello from custom logger example!',
    );
  } catch (e) {
    print('Error: $e');
  }
}
```

#### Custom log formatting

```dart
import 'package:pubnub/pubnub.dart';
import 'package:pubnub/logging.dart';

void main() {
  // Create a logger with name 'myApp' that logs everything
  final logger = StreamLogger.root('myApp', logLevel: Level.all);
  
  // Listen to the log stream and format messages
  logger.stream.listen((record) {
    print('[${record.time}] ${Level.getName(record.level)}: ${record.message}');
  });
  
  // Initialize PubNub with demo keys
  final pubnub = PubNub(
    defaultKeyset: Keyset(
      subscribeKey: 'demo', // Replace with your Subscribe Key from the PubNub Admin Portal
      publishKey: 'demo',   // Replace with your Publish Key from the PubNub Admin Portal
      userId: UserId('loggingDemoUser'),
    ),
  );
  
  print('Logger initialized with custom log formatting');
}
```

#### Default printer

If all you want to do is to print the messages to the output you can use a `LogRecord.defaultPrinter` and pass that as a listener to the logger stream.

```dart
import 'package:pubnub/pubnub.dart';
import 'package:pubnub/logging.dart';

void main() {
  // Create a logger with name 'myApp' that logs everything
  final logger = StreamLogger.root('myApp', logLevel: Level.all);
  
  // Use the built-in default printer
  logger.stream.listen(LogRecord.defaultPrinter);
  
  // Initialize PubNub with demo keys
  final pubnub = PubNub(
    defaultKeyset: Keyset(
      subscribeKey: 'demo', // Replace with your Subscribe Key from the PubNub Admin Portal
      publishKey: 'demo',   // Replace with your Publish Key from the PubNub Admin Portal
      userId: UserId('loggingDemoUser'),
    ),
  );
  
  print('Logger initialized with default printer');
}
```

### Zone-scoped logging for Flutter apps

In case of a Flutter app, you can wrap the entire `runApp` method.

```dart
import 'package:flutter/material.dart';
import 'package:pubnub/pubnub.dart';
import 'package:pubnub/logging.dart';

// Simple Flutter app for demo purposes
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('PubNub Logging Example')),
        body: Center(child: Text('Check console for logs')),
      ),
    );
  }
}

void main() {
  // Create a logger with name 'myApp' that logs everything
  final logger = StreamLogger.root('myApp', logLevel: Level.all);
  logger.stream.listen(LogRecord.defaultPrinter);
  
  // Wrap the entire app with logging
  provideLogger(logger, () {
    runApp(MyApp());
    
    // Create a PubNub instance to generate some logs
    final pubnub = PubNub(
      defaultKeyset: Keyset(
        subscribeKey: 'demo', // Replace with your Subscribe Key from the PubNub Admin Portal
        publishKey: 'demo',   // Replace with your Publish Key from the PubNub Admin Portal
        userId: UserId('loggingDemoUser'),
      ),
    );
    
    // This will generate logs visible in the console
    pubnub.time();
  });
}
```

## Logged information

The Dart SDK logs information at various stages of operation:

* API operations (for example, `publish`, `subscribe`, `time`)
* Network requests and responses
* Instance initialization details
* Configuration changes
* Error conditions and exceptions

This provides complete visibility into SDK behavior for debugging and monitoring.

## Custom loggers

Implement the `ILogger` interface to create custom loggers that route logs to external monitoring services, databases, or analytics platforms.

### ILogger interface

The `ILogger` interface defines the requirements for a logger:

```dart
abstract class ILogger {
  /// Get a child logger with the given id
  ILogger get(String id);
  
  /// Log a message at the given level
  void log(int level, dynamic message);
}
```

Custom loggers can process log messages and route them to any destination. You can use custom loggers alongside `StreamLogger` by wrapping them in a `CompositeLogger` or by implementing your own logging strategy.

## Logging best practices

Use these recommendations for effective logging.

### Choose the right log level

| Environment | Recommended Log Level |
| --- | --- |
| Production | `Level.off` or `Level.warning` to capture issues without performance impact. |
| Staging | `Level.info` to monitor operational events. |
| Development | `Level.all` or `Level.verbose` when actively developing or investigating issues. |
| Deep troubleshooting | `Level.all` with `provideLogger` scoped to specific code paths. |

### Protect sensitive data

Never enable detailed logging (`Level.all`, `Level.silly`, `Level.fine`, `Level.verbose`) in production environments that handle sensitive information.

These levels may expose:

* API keys
* User identifiers
* Message content

### Use zone-scoped logging strategically

Use `provideLogger` to enable logging only for specific code paths during debugging. This reduces noise and focuses on the problematic areas:

```dart
// Only log the troublesome function
await provideLogger(logger, () async {
  await troublesomeFunction();
});
```

### Monitor log volume

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

### Optimize performance in production

Disable logging in production or set the log level to `Level.off` or `Level.warning` only. This optimizes performance and reduces storage costs:

```dart
// For production builds
final pubnub = PubNub(
  defaultKeyset: Keyset(
    subscribeKey: subscribeKey,
    publishKey: publishKey,
    userId: userId,
  ),
  logging: LoggingConfiguration(
    logLevel: Level.off,  // Disable logging completely
  ),
);
```

### Provide logs to support

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

1. Set the log level to `Level.all`.
2. Subscribe to the log stream with `LogRecord.defaultPrinter` or custom formatting.
3. Reproduce the issue.
4. Collect logs from initialization through the problem occurrence.
5. Include the PubNub SDK version.

For more information about configuration parameters, refer to [Configuration](https://www.pubnub.com/docs/sdks/dart/api-reference/configuration).