ispectify_ws 4.3.4
ispectify_ws: ^4.3.4 copied to clipboard
An additional package for ws (logging and handling).
Overview #
ISpectify WebSocket integrates the ws package with the ISpectify logging system for WebSocket monitoring.
ISpectifyWS integrates the ws package with the ISpectify logging system for WebSocket monitoring.
Key Features #
- WebSocket Connection Logging: Automatic logging of all WebSocket connections
- Message Tracking: Detailed logging of sent and received messages
- Error Handling: Comprehensive error logging with stack traces
- Connection Inspection: URL, connection state, and metrics logging
- Sensitive Data Redaction: Centralized redaction for sent/received payloads (enabled by default, configurable)
- Performance Metrics: Connection timing and message count tracking
- Lightweight: Minimal overhead using ws package interceptors
Configuration Options #
Basic Setup #
final logger = ISpectify();
final interceptor = ISpectWSInterceptor(
logger: logger,
settings: const ISpectWSInterceptorSettings(
enabled: true,
printSentData: true,
printReceivedData: true,
printReceivedMessage: true,
printErrorData: true,
printErrorMessage: true,
printReceivedHeaders: false,
),
);
final client = WebSocketClient(
WebSocketOptions.common(
interceptors: [interceptor],
),
);
interceptor.setClient(client);
Sensitive Data Redaction #
Redaction is enabled by default. Disable only with synthetic / non-sensitive data.
final interceptor = ISpectWSInterceptor(
logger: logger,
settings: const ISpectWSInterceptorSettings(enableRedaction: false),
);
final redactor = RedactionService();
redactor.ignoreKeys(['x-debug']);
redactor.ignoreValues(['<placeholder-token>']);
final interceptor2 = ISpectWSInterceptor(
logger: logger,
redactor: redactor,
);
Filtering with Optional Predicates #
final interceptor = ISpectWSInterceptor(
logger: logger,
settings: ISpectWSInterceptorSettings(
enabled: true,
sentFilter: (request) => request.body?['data']?.toString().contains('important') ?? false,
receivedFilter: (response) => !(response.body?['data']?.toString().contains('error') ?? false),
errorFilter: (error) => true,
sentPen: AnsiPen()..blue(),
receivedPen: AnsiPen()..green(),
errorPen: AnsiPen()..red(),
),
);
Connection Event Handling #
final interceptor = ISpectWSInterceptor(
logger: logger,
onClientReady: (client) {
print('WebSocket client is ready');
print('Client metrics: ${client.metrics}');
},
);
Installation #
Add ispectify_ws to your pubspec.yaml:
dependencies:
ispectify_ws: ^4.3.4
Security & Production Guidelines #
IMPORTANT: ISpect is a debugging tool and should NEVER be included in production builds
Production Safety #
ISpect contains sensitive debugging information and should only be used in development and staging environments. To ensure ISpect is completely removed from production builds, use the following approach:
Recommended Setup with Dart Define Constants #
1. Create environment-aware initialization:
// main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
// Use dart define to control ISpect inclusion
const bool kEnableISpect = bool.fromEnvironment('ENABLE_ISPECT', defaultValue: false);
void main() {
if (kEnableISpect) {
// Initialize ISpect only in development/staging
_initializeISpect();
} else {
// Production initialization without ISpect
runApp(MyApp());
}
}
void _initializeISpect() {
// ISpect initialization code here
// This entire function will be tree-shaken in production
}
2. Build Commands:
# Development build (includes ISpect)
flutter run --dart-define=ENABLE_ISPECT=true
# Staging build (includes ISpect)
flutter build appbundle --dart-define=ENABLE_ISPECT=true
# Production build (ISpect completely removed via tree-shaking)
flutter build appbundle --dart-define=ENABLE_ISPECT=false
# or simply:
flutter build appbundle # defaults to false
3. Conditional Widget Wrapping:
Widget build(BuildContext context) {
return MaterialApp(
// Conditionally add ISpectBuilder in MaterialApp builder
builder: (context, child) {
if (kEnableISpect) {
return ISpectBuilder(child: child ?? const SizedBox.shrink());
}
return child ?? const SizedBox.shrink();
},
home: Scaffold(/* your app content */),
);
}
Security Benefits #
- Zero Production Footprint: Tree-shaking removes all ISpect code from release builds
- No Sensitive Data Exposure: Debug information never reaches production users
- Performance Optimized: No debugging overhead in production
- Compliance Ready: Meets security requirements for app store releases
🔍 Verification #
To verify ISpect is not included in your production build:
# Build release APK and check size difference
flutter build apk --dart-define=ENABLE_ISPECT=false --release
flutter build apk --dart-define=ENABLE_ISPECT=true --release
# Use flutter tools to analyze bundle
flutter analyze --dart-define=ENABLE_ISPECT=false
🚀 Quick Start #
import 'dart:async';
import 'dart:io' as io show exit;
import 'package:flutter/foundation.dart';
import 'package:ispectify/ispectify.dart';
import 'package:ispectify_ws/ispectify_ws.dart';
import 'package:ws/ws.dart';
// Use dart define to control ISpectify WebSocket integration
const bool kEnableISpectWS = bool.fromEnvironment('ENABLE_ISPECT', defaultValue: false);
void main() {
// Replace with your test endpoint or local dev server; avoid deprecated public echo services
const url = 'wss://example.com/socket';
if (kEnableISpectWS) {
_initializeWithISpect(url);
} else {
_initializeWithoutISpect(url);
}
}
void _initializeWithISpect(String url) {
final logger = ISpectify();
final interceptor = ISpectWSInterceptor(
logger: logger,
settings: const ISpectWSInterceptorSettings(
enabled: true,
printSentData: true,
printReceivedData: true,
printErrorData: true,
enableRedaction: true, // Keep redaction enabled for any non-local traffic
),
);
final client = WebSocketClient(
WebSocketOptions.common(
connectionRetryInterval: (
min: const Duration(milliseconds: 500),
max: const Duration(seconds: 15),
),
interceptors: [interceptor],
),
);
interceptor.setClient(client);
_runWebSocketExample(client, url);
}
void _initializeWithoutISpect(String url) {
final client = WebSocketClient(
WebSocketOptions.common(
connectionRetryInterval: (
min: const Duration(milliseconds: 500),
max: const Duration(seconds: 15),
),
),
);
_runWebSocketExample(client, url);
}
void _runWebSocketExample(WebSocketClient client, String url) {
client
..connect(url)
..add('Hello WebSocket!');
client.stream.listen(
(message) {
print('Received: $message');
},
onError: (error) {
print('Error: $error');
},
);
Timer(const Duration(seconds: 5), () async {
await client.close();
print('Connection closed');
if (kEnableISpectWS) {
print('Metrics: ${client.metrics}');
}
});
}
Examples #
See the example/ directory for complete integration examples with different WebSocket client configurations.
🏗️ Architecture #
ISpectifyWS integrates with the WebSocket client through interceptors:
| Component | Description |
|---|---|
| WS Interceptor | Captures WebSocket connection events and messages |
| Message Logger | Logs sent and received message details |
| Connection Logger | Logs connection state and URL information |
| Error Handler | Captures and logs WebSocket errors |
| Metrics Tracker | Measures connection timing and message counts |
🤝 Contributing #
Contributions are welcome! Please read our contributing guidelines and submit pull requests to the main branch.
📄 License #
This project is licensed under the MIT License - see the LICENSE file for details.
Related Packages #
- ispectify - Foundation logging system
- ispectify_dio - Dio HTTP client integration
- ispectify_http - HTTP client integration
- ispect - Main debugging interface
- ws - WebSocket client package for Dart