[READ ONLY MIRROR] Open Source TikTok alternative built on AT Protocol github.com/sprksocial/client
flutter atproto video dart
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160import 'dart:developer' as developer;import 'dart:io';
import 'package:path_provider/path_provider.dart';import 'package:spark/src/core/utils/logging/log_level.dart';import 'package:spark/src/core/utils/logging/log_output.dart';import 'package:synchronized/synchronized.dart';
/// Outputs logs to a fileclass FileOutput implements LogOutput { /// Constructor FileOutput({ this._fileName = 'spark_app.log', this._maxFileSize = 10 * 1024 * 1024, // 10 MB });
/// The file to write logs to File? _file;
/// Lock to prevent concurrent file access final Lock _lock = Lock();
/// The path to the log file final String _fileName;
/// Maximum file size in bytes (default: 10MB) final int _maxFileSize;
/// Whether the file has been initialized bool _initialized = false;
/// Initialize the file output Future<void> initialize() async { if (_initialized) return;
try { final directory = await getApplicationDocumentsDirectory(); final path = '${directory.path}/logs'; await Directory(path).create(recursive: true); _file = File('$path/$_fileName'); _initialized = true; } catch (e, stackTrace) { _reportFileLoggingFailure( 'Failed to initialize file logging', e, stackTrace, ); } }
@override void output( LogLevel level, String message, DateTime timestamp, Object? error, StackTrace? stackTrace, ) { _lock.synchronized(() async { if (!_initialized) { await initialize(); }
if (_file == null) return;
try { final timeString = _formatTime(timestamp); final levelString = '[${level.name}]'.padRight(9); final prefix = '$timeString $levelString';
final buffer = StringBuffer('$prefix $message\n');
if (error != null) { buffer.write('Error: $error\n'); }
if (stackTrace != null) { buffer.write('Stack trace:\n$stackTrace\n'); }
// Check file size and rotate if necessary if (await _shouldRotateLog()) { await _rotateLog(); }
// Append to file await _file!.writeAsString( buffer.toString(), mode: FileMode.append, flush: true, // Ensure it's written immediately ); } catch (e, stackTrace) { _reportFileLoggingFailure('Failed to write to log file', e, stackTrace); } }); }
/// Format time as YYYY-MM-DD HH:MM:SS.mmm String _formatTime(DateTime time) { return '${time.year}-' '${time.month.toString().padLeft(2, '0')}-' '${time.day.toString().padLeft(2, '0')} ' '${time.hour.toString().padLeft(2, '0')}:' '${time.minute.toString().padLeft(2, '0')}:' '${time.second.toString().padLeft(2, '0')}.' '${time.millisecond.toString().padLeft(3, '0')}'; }
/// Checks if the log file should be rotated Future<bool> _shouldRotateLog() async { if (_file == null) return false;
try { final fileStats = _file!.statSync(); return fileStats.size > _maxFileSize; } catch (e) { return false; } }
/// Rotates the log file by renaming it with a timestamp Future<void> _rotateLog() async { if (_file == null) return;
try { final now = DateTime.now(); final timestamp = '${now.year}${now.month.toString().padLeft(2, '0')}' '${now.day.toString().padLeft(2, '0')}' '${now.hour.toString().padLeft(2, '0')}' '${now.minute.toString().padLeft(2, '0')}' '${now.second.toString().padLeft(2, '0')}';
final directory = _file!.parent; final oldFilePath = _file!.path; final newFilePath = '${directory.path}/${_fileName.split('.').first}.$timestamp.log';
await _file!.rename(newFilePath); _file = File(oldFilePath); } catch (e, stackTrace) { _reportFileLoggingFailure('Failed to rotate log file', e, stackTrace); } }
void _reportFileLoggingFailure( String message, Object error, StackTrace stackTrace, ) { developer.log( message, name: 'FileOutput', level: LogLevel.error.value * 100, error: error, stackTrace: stackTrace, ); }}