On this page

Logging for Dart SDK

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.

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.

LevelWeightPurpose
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 documentation.

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.

1import 'package:pubnub/pubnub.dart';
2import 'package:pubnub/logging.dart';
3
4void main() async {
5 final pubnub = PubNub(
6 defaultKeyset: Keyset(
7 subscribeKey: 'demo', // Replace with your Subscribe Key from the PubNub Admin Portal
8 publishKey: 'demo', // Replace with your Publish Key from the PubNub Admin Portal
9 userId: UserId('loggingDemoUser'),
10 ),
11 logging: LoggingConfiguration(
12 logLevel: Level.all, // Enable all logs
13 logToConsole: true, // Optional: print formatted logs to console automatically
14 // loggerName: 'myApp', // Optional: custom logger name
15 ),
show all 17 lines

Change log level at runtime

Adjust the log level dynamically during application execution:

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

Enable custom logging

1import 'package:pubnub/pubnub.dart';
2
3class JsonLogger implements ILogger {
4
5 void log(int level, dynamic message) {
6 final logEntry = {
7 'timestamp': DateTime.now().toIso8601String(),
8 'level': Level.getName(level),
9 'message': message.toString(),
10 'service': 'pubnub',
11 };
12 // implement method that communicates with external logging service.
13 // sendToLoggingService(jsonEncode(logEntry));
14 }
15
show all 51 lines

Custom log formatting

1import 'package:pubnub/pubnub.dart';
2import 'package:pubnub/logging.dart';
3
4void main() {
5 // Create a logger with name 'myApp' that logs everything
6 final logger = StreamLogger.root('myApp', logLevel: Level.all);
7
8 // Listen to the log stream and format messages
9 logger.stream.listen((record) {
10 print('[${record.time}] ${Level.getName(record.level)}: ${record.message}');
11 });
12
13 // Initialize PubNub with demo keys
14 final pubnub = PubNub(
15 defaultKeyset: Keyset(
show all 23 lines

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.

1import 'package:pubnub/pubnub.dart';
2import 'package:pubnub/logging.dart';
3
4void main() {
5 // Create a logger with name 'myApp' that logs everything
6 final logger = StreamLogger.root('myApp', logLevel: Level.all);
7
8 // Use the built-in default printer
9 logger.stream.listen(LogRecord.defaultPrinter);
10
11 // Initialize PubNub with demo keys
12 final pubnub = PubNub(
13 defaultKeyset: Keyset(
14 subscribeKey: 'demo', // Replace with your Subscribe Key from the PubNub Admin Portal
15 publishKey: 'demo', // Replace with your Publish Key from the PubNub Admin Portal
show all 21 lines

Zone-scoped logging for Flutter apps

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

1import 'package:flutter/material.dart';
2import 'package:pubnub/pubnub.dart';
3import 'package:pubnub/logging.dart';
4
5// Simple Flutter app for demo purposes
6class MyApp extends StatelessWidget {
7
8 Widget build(BuildContext context) {
9 return MaterialApp(
10 home: Scaffold(
11 appBar: AppBar(title: Text('PubNub Logging Example')),
12 body: Center(child: Text('Check console for logs')),
13 ),
14 );
15 }
show all 39 lines

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:

1abstract class ILogger {
2 /// Get a child logger with the given id
3 ILogger get(String id);
4
5 /// Log a message at the given level
6 void log(int level, dynamic message);
7}

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

EnvironmentRecommended 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:

1// Only log the troublesome function
2await provideLogger(logger, () async {
3 await troublesomeFunction();
4});

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:

1// For production builds
2final pubnub = PubNub(
3 defaultKeyset: Keyset(
4 subscribeKey: subscribeKey,
5 publishKey: publishKey,
6 userId: userId,
7 ),
8 logging: LoggingConfiguration(
9 logLevel: Level.off, // Disable logging completely
10 ),
11);

Provide logs to support

When reporting issues to PubNub support, 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.

Last updated on