stack_wallet/lib/utilities/logger.dart

168 lines
4.5 KiB
Dart

/*
* This file is part of Stack Wallet.
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.
* Generated by Cypher Stack on 2023-05-26
*
*/
import 'dart:core' as core;
import 'dart:core';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:isar/isar.dart';
import '../models/isar/models/log.dart';
import 'constants.dart';
import 'enums/log_level_enum.dart';
export 'enums/log_level_enum.dart';
class Logging {
static const isArmLinux = bool.fromEnvironment("IS_ARM");
static final isTestEnv = Platform.environment["FLUTTER_TEST"] == "true";
Logging._();
static final Logging _instance = Logging._();
static Logging get instance => _instance;
static const core.int defaultPrintLength = 1020;
late final Isar? isar;
late final _AsyncLogWriterQueue _queue;
Future<void> init(Isar isar) async {
_queue = _AsyncLogWriterQueue();
this.isar = isar;
}
void log(
core.Object? object, {
required LogLevel level,
core.bool printToConsole = true,
core.bool printFullLength = false,
}) {
try {
if (isTestEnv || isArmLinux) {
Logger.print(object, normalLength: !printFullLength);
return;
}
String message = object.toString();
// random value to check max size of message before storing in db
if (message.length > 20000) {
message = "${message.substring(0, 20000)}...";
}
final now = core.DateTime.now().toUtc();
final log = Log()
..message = message
..logLevel = level
..timestampInMillisUTC = now.millisecondsSinceEpoch;
if (level == LogLevel.Error || level == LogLevel.Fatal) {
printFullLength = true;
}
_queue.add(
() async => isar!.writeTxn(
() async => await isar!.logs.put(log),
),
);
if (printToConsole) {
final core.String logStr = "Log: ${log.toString()}";
final core.int logLength = logStr.length;
if (!printFullLength || logLength <= defaultPrintLength) {
debugPrint(logStr);
} else {
core.int start = 0;
core.int endIndex = defaultPrintLength;
core.int tmpLogLength = logLength;
while (endIndex < logLength) {
debugPrint(logStr.substring(start, endIndex));
endIndex += defaultPrintLength;
start += defaultPrintLength;
tmpLogLength -= defaultPrintLength;
}
if (tmpLogLength > 0) {
debugPrint(logStr.substring(start, logLength));
}
}
}
} catch (e, s) {
print("problem trying to log");
print("$e $s");
Logger.print(object);
}
}
}
abstract class Logger {
static final isTestEnv = Platform.environment["FLUTTER_TEST"] == "true";
static void print(
core.Object? object, {
core.bool withTimeStamp = true,
core.bool normalLength = true,
}) async {
if (Constants.disableLogger && !isTestEnv) {
return;
}
final utcTime = withTimeStamp ? "${core.DateTime.now().toUtc()}: " : "";
final core.int defaultPrintLength = 1020 - utcTime.length;
if (normalLength) {
debugPrint("$utcTime$object");
} else if (object == null ||
object.toString().length <= defaultPrintLength) {
debugPrint("$utcTime$object");
} else {
final core.String log = object.toString();
core.int start = 0;
core.int endIndex = defaultPrintLength;
final core.int logLength = log.length;
core.int tmpLogLength = log.length;
while (endIndex < logLength) {
debugPrint(utcTime + log.substring(start, endIndex));
endIndex += defaultPrintLength;
start += defaultPrintLength;
tmpLogLength -= defaultPrintLength;
}
if (tmpLogLength > 0) {
debugPrint(utcTime + log.substring(start, logLength));
}
}
}
}
/// basic async queue for writing logs in the [Logging] to isar
class _AsyncLogWriterQueue {
final List<Future<void> Function()> _queue = [];
bool _runningLock = false;
void add(Future<void> Function() futureFunction) {
_queue.add(futureFunction);
_run();
}
void _run() async {
if (_runningLock) {
return;
}
_runningLock = true;
try {
while (_queue.isNotEmpty) {
final futureFunction = _queue.removeAt(0);
try {
await futureFunction.call();
} catch (e, s) {
debugPrint("$e\n$s");
}
}
} finally {
_runningLock = false;
}
}
}