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
StreamLoggerthat outputs to streams for flexible consumption - Custom loggers: Implement the
ILoggerinterface 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 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 linesChange 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 linesCustom 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 linesDefault 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 linesZone-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 linesLogged 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
| 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:
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:
- Set the log level to
Level.all. - Subscribe to the log stream with
LogRecord.defaultPrinteror custom formatting. - Reproduce the issue.
- Collect logs from initialization through the problem occurrence.
- Include the PubNub SDK version.
For more information about configuration parameters, refer to Configuration.