Clone super_logging and make it privacy friendly
This commit is contained in:
parent
7397f08f0f
commit
06b679fca8
9 changed files with 769 additions and 5 deletions
|
@ -752,10 +752,10 @@ packages:
|
|||
super_logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: super_logging
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
path: "thirdparty/super_logging"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.3.4"
|
||||
supercharged:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -37,7 +37,8 @@ dependencies:
|
|||
visibility_detector: ^0.1.5
|
||||
event_bus: ^1.1.1
|
||||
sentry: ">=3.0.0 <4.0.0"
|
||||
super_logging: ^2.0.1
|
||||
super_logging:
|
||||
path: thirdparty/super_logging
|
||||
archive: ^2.0.11
|
||||
flutter_email_sender: ^3.0.1
|
||||
like_button: ^0.2.0
|
||||
|
|
239
thirdparty/super_logging/.gitignore
vendored
Normal file
239
thirdparty/super_logging/.gitignore
vendored
Normal file
|
@ -0,0 +1,239 @@
|
|||
.DS_Store
|
||||
.dart_tool/
|
||||
|
||||
flutter_export_environment.sh
|
||||
.flutter-plugins-dependencies
|
||||
|
||||
.packages
|
||||
.pub/
|
||||
|
||||
build/
|
||||
ios/.generated/
|
||||
ios/Flutter/Generated.xcconfig
|
||||
ios/Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
**/.idea
|
||||
.flutter-plugins
|
||||
|
||||
android/
|
||||
|
||||
# Created by https://www.gitignore.io/api/dart,android,androidstudio
|
||||
# Edit at https://www.gitignore.io/?templates=dart,android,androidstudio
|
||||
|
||||
### Android ###
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
# Android Studio Navigation editor temp files
|
||||
.navigation/
|
||||
|
||||
# Android Studio captures folder
|
||||
captures/
|
||||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/gradle.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/dictionaries
|
||||
.idea/libraries
|
||||
.idea/caches
|
||||
# Android Studio 3 in .gitignore file.
|
||||
.idea/caches/build_file_checksums.ser
|
||||
.idea/modules.xml
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||
#*.jks
|
||||
#*.keystore
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
|
||||
# Freeline
|
||||
freeline.py
|
||||
freeline/
|
||||
freeline_project_description.json
|
||||
|
||||
# fastlane
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
fastlane/readme.md
|
||||
|
||||
# Version control
|
||||
vcs.xml
|
||||
|
||||
# lint
|
||||
lint/intermediates/
|
||||
lint/generated/
|
||||
lint/outputs/
|
||||
lint/tmp/
|
||||
# lint/reports/
|
||||
|
||||
### Android Patch ###
|
||||
gen-external-apklibs
|
||||
output.json
|
||||
|
||||
### AndroidStudio ###
|
||||
# Covers files to be ignored for android development using Android Studio.
|
||||
|
||||
# Built application files
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
|
||||
# Java class files
|
||||
|
||||
# Generated files
|
||||
|
||||
# Gradle files
|
||||
.gradle
|
||||
|
||||
# Signing files
|
||||
.signing/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
|
||||
# Log Files
|
||||
|
||||
# Android Studio
|
||||
/*/build/
|
||||
/*/local.properties
|
||||
/*/out
|
||||
/*/*/build
|
||||
/*/*/production
|
||||
*.ipr
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# Android Patch
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
|
||||
# NDK
|
||||
obj/
|
||||
|
||||
# IntelliJ IDEA
|
||||
*.iws
|
||||
/out/
|
||||
|
||||
# User-specific configurations
|
||||
.idea/caches/
|
||||
.idea/libraries/
|
||||
.idea/shelf/
|
||||
.idea/.name
|
||||
.idea/compiler.xml
|
||||
.idea/copyright/profiles_settings.xml
|
||||
.idea/encodings.xml
|
||||
.idea/misc.xml
|
||||
.idea/scopes/scope_settings.xml
|
||||
.idea/vcs.xml
|
||||
.idea/jsLibraryMappings.xml
|
||||
.idea/datasources.xml
|
||||
.idea/dataSources.ids
|
||||
.idea/sqlDataSources.xml
|
||||
.idea/dynamic.xml
|
||||
.idea/uiDesigner.xml
|
||||
|
||||
# OS-specific files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Legacy Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
.cproject
|
||||
.settings/
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
|
||||
hs_err_pid*
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/mongoSettings.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
### AndroidStudio Patch ###
|
||||
|
||||
!/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
### Dart ###
|
||||
# See https://www.dartlang.org/guides/libraries/private-files
|
||||
|
||||
# Files and directories created by pub
|
||||
.dart_tool/
|
||||
.packages
|
||||
# If you're building an application, you may want to check-in your pubspec.lock
|
||||
pubspec.lock
|
||||
|
||||
# Directory created by dartdoc
|
||||
# If you don't generate documentation locally you can remove this line.
|
||||
doc/api/
|
||||
|
||||
# Avoid committing generated Javascript files:
|
||||
*.dart.js
|
||||
*.info.json # Produced by the --dump-info flag.
|
||||
*.js # When generated by dart2js. Don't specify *.js if your
|
||||
# project includes source files written in JavaScript.
|
||||
*.js_
|
||||
*.js.deps
|
||||
*.js.map
|
||||
|
||||
# End of https://www.gitignore.io/api/dart,android,androidstudio
|
10
thirdparty/super_logging/.metadata
vendored
Normal file
10
thirdparty/super_logging/.metadata
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 8661d8aecd626f7f57ccbcb735553edc05a2e713
|
||||
channel: stable
|
||||
|
||||
project_type: package
|
21
thirdparty/super_logging/LICENSE
vendored
Normal file
21
thirdparty/super_logging/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 PyCampers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
54
thirdparty/super_logging/README.md
vendored
Normal file
54
thirdparty/super_logging/README.md
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
# Super Logging
|
||||
|
||||
[](https://www.jaaga.in/labs)
|
||||
|
||||
[](https://pub.dartlang.org/packages/super_logging)
|
||||
|
||||
This package lets you easily log to:
|
||||
- stdout
|
||||
- disk
|
||||
- sentry.io
|
||||
|
||||
```dart
|
||||
import 'package:super_logging/super_logging.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
final logger = Logger("main");
|
||||
|
||||
main() async {
|
||||
// just call once, and let it handle the rest!
|
||||
await SuperLogging.main();
|
||||
|
||||
logger.info("hello!");
|
||||
}
|
||||
```
|
||||
|
||||
(Above example will log to stdout and disk.)
|
||||
|
||||
## Logging to sentry.io
|
||||
|
||||
Just specify your sentry DSN.
|
||||
|
||||
```dart
|
||||
SuperLogging.main(LogConfig(
|
||||
sentryDsn: 'https://xxxx@sentry.io/yyyy',
|
||||
));
|
||||
```
|
||||
|
||||
## Log uncaught errors
|
||||
|
||||
Just provide the contents of your `main()` function to super logging.
|
||||
|
||||
```dart
|
||||
void main() {
|
||||
SuperLogging.main(LogConfig(
|
||||
body: _main,
|
||||
));
|
||||
}
|
||||
|
||||
void _main() {
|
||||
runApp(MyApp());
|
||||
}
|
||||
```
|
||||
|
||||
[Read the docs](https://pub.dev/documentation/super_logging/latest/super_logging/super_logging-library.html) to know about more customization options.
|
323
thirdparty/super_logging/lib/super_logging.dart
vendored
Normal file
323
thirdparty/super_logging/lib/super_logging.dart
vendored
Normal file
|
@ -0,0 +1,323 @@
|
|||
library super_logging;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:sentry/sentry.dart';
|
||||
|
||||
export 'package:sentry/sentry.dart' show User;
|
||||
|
||||
typedef FutureOr<void> FutureOrVoidCallback();
|
||||
|
||||
extension SuperString on String {
|
||||
Iterable<String> chunked(int chunkSize) sync* {
|
||||
var start = 0;
|
||||
|
||||
while (true) {
|
||||
var stop = start + chunkSize;
|
||||
if (stop > length) break;
|
||||
yield substring(start, stop);
|
||||
start = stop;
|
||||
}
|
||||
|
||||
if (start < length) {
|
||||
yield substring(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SuperLogRecord on LogRecord {
|
||||
String toPrettyString([String extraLines]) {
|
||||
var header = "[$loggerName] [$level] [$time]";
|
||||
|
||||
var msg = "$header $message";
|
||||
|
||||
if (error != null) {
|
||||
msg += "\n⤷ type: ${error.runtimeType}\n⤷ error: $error";
|
||||
}
|
||||
if (stackTrace != null) {
|
||||
msg += "\n⤷ trace: $stackTrace";
|
||||
}
|
||||
|
||||
for (var line in extraLines?.split('\n') ?? []) {
|
||||
msg += '\n$header $line';
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
Event toEvent({String appVersion}) {
|
||||
return Event(
|
||||
release: appVersion,
|
||||
level: SeverityLevel.error,
|
||||
culprit: message,
|
||||
loggerName: loggerName,
|
||||
exception: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LogConfig {
|
||||
/// The DSN for a Sentry app.
|
||||
/// This can be obtained from the Sentry apps's "settings > Client Keys (DSN)" page.
|
||||
///
|
||||
/// Only logs containing errors are sent to sentry.
|
||||
/// Errors can be caught using a try-catch block, like so:
|
||||
///
|
||||
/// ```
|
||||
/// final logger = Logger("main");
|
||||
///
|
||||
/// try {
|
||||
/// // do something dangerous here
|
||||
/// } catch(e, trace) {
|
||||
/// logger.info("Huston, we have a problem", e, trace);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If this is [null], Sentry logger is completely disabled (default).
|
||||
String sentryDsn;
|
||||
|
||||
/// A built-in retry mechanism for sending errors to sentry.
|
||||
///
|
||||
/// This parameter defines the time to wait for, before retrying.
|
||||
Duration sentryRetryDelay;
|
||||
|
||||
/// Path of the directory where log files will be stored.
|
||||
///
|
||||
/// If this is [null], file logging is completely disabled (default).
|
||||
///
|
||||
/// If this is an empty string (['']),
|
||||
/// then a 'logs' directory will be created in [getTemporaryDirectory()].
|
||||
///
|
||||
/// A non-empty string will be treated as an explicit path to a directory.
|
||||
///
|
||||
/// The chosen directory can be accessed using [SuperLogging.logFile.parent].
|
||||
String logDirPath;
|
||||
|
||||
/// The maximum number of log files inside [logDirPath].
|
||||
///
|
||||
/// One log file is created per day.
|
||||
/// Older log files are deleted automatically.
|
||||
int maxLogFiles;
|
||||
|
||||
/// Whether to enable super logging features in debug mode.
|
||||
///
|
||||
/// Sentry and file logging are typically not needed in debug mode,
|
||||
/// where a complete logcat is available.
|
||||
bool enableInDebugMode;
|
||||
|
||||
/// If provided, super logging will invoke this function, and
|
||||
/// any uncaught errors during its execution will be reported.
|
||||
///
|
||||
/// Works by using [FlutterError.onError] and [runZoned].
|
||||
FutureOrVoidCallback body;
|
||||
|
||||
/// The date format for storing log files.
|
||||
///
|
||||
/// `DateFormat('y-M-d')` by default.
|
||||
DateFormat dateFmt;
|
||||
|
||||
LogConfig({
|
||||
this.sentryDsn,
|
||||
this.sentryRetryDelay = const Duration(seconds: 30),
|
||||
this.logDirPath,
|
||||
this.maxLogFiles = 10,
|
||||
this.enableInDebugMode = false,
|
||||
this.body,
|
||||
this.dateFmt,
|
||||
}) {
|
||||
dateFmt ??= DateFormat("y-M-d");
|
||||
}
|
||||
}
|
||||
|
||||
class SuperLogging {
|
||||
/// The logger for SuperLogging
|
||||
static final $ = Logger('ente_logging');
|
||||
|
||||
/// The current super logging configuration
|
||||
static LogConfig config;
|
||||
|
||||
static Future<void> main([LogConfig config]) async {
|
||||
config ??= LogConfig();
|
||||
SuperLogging.config = config;
|
||||
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
appVersion ??= await getAppVersion();
|
||||
|
||||
final enable = config.enableInDebugMode || kReleaseMode;
|
||||
sentryIsEnabled = enable && config.sentryDsn != null;
|
||||
fileIsEnabled = enable && config.logDirPath != null;
|
||||
|
||||
if (fileIsEnabled) {
|
||||
await setupLogDir();
|
||||
}
|
||||
if (sentryIsEnabled) {
|
||||
sentryUploader();
|
||||
}
|
||||
|
||||
Logger.root.level = Level.ALL;
|
||||
Logger.root.onRecord.listen(onLogRecord);
|
||||
|
||||
if (!enable) {
|
||||
$.info("detected debug mode; sentry & file logging disabled.");
|
||||
}
|
||||
if (fileIsEnabled) {
|
||||
$.info("using this log file for today: $logFile");
|
||||
}
|
||||
if (sentryIsEnabled) {
|
||||
$.info("sentry uploader started");
|
||||
}
|
||||
|
||||
if (config.body == null) return;
|
||||
|
||||
if (enable) {
|
||||
FlutterError.onError = (details) {
|
||||
$.fine(
|
||||
"uncaught error from FlutterError.onError()",
|
||||
details.exception,
|
||||
details.stack,
|
||||
);
|
||||
};
|
||||
await runZoned(config.body, onError: (e, trace) {
|
||||
$.fine("uncaught error from runZoned()", e, trace);
|
||||
});
|
||||
} else {
|
||||
await config.body();
|
||||
}
|
||||
}
|
||||
|
||||
static var _lastExtraLines = '';
|
||||
|
||||
static Future onLogRecord(LogRecord rec) async {
|
||||
// log misc info if it changed
|
||||
var extraLines = "app version: '$appVersion'\n";
|
||||
if (extraLines != _lastExtraLines) {
|
||||
_lastExtraLines = extraLines;
|
||||
} else {
|
||||
extraLines = null;
|
||||
}
|
||||
|
||||
var str = rec.toPrettyString(extraLines);
|
||||
|
||||
// write to stdout
|
||||
printLog(str);
|
||||
|
||||
// write to logfile
|
||||
if (fileIsEnabled) {
|
||||
final strForLogFile = str + '\n';
|
||||
await logFile.writeAsString(strForLogFile,
|
||||
mode: FileMode.append, flush: true);
|
||||
}
|
||||
|
||||
// add error to sentry queue
|
||||
if (sentryIsEnabled && rec.error != null) {
|
||||
var event = rec.toEvent(appVersion: appVersion);
|
||||
sentryQueueControl.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Logs on must be chunked or they get truncated otherwise
|
||||
// See https://github.com/flutter/flutter/issues/22665
|
||||
static var logChunkSize = 800;
|
||||
|
||||
static void printLog(String text) {
|
||||
text.chunked(logChunkSize).forEach(print);
|
||||
}
|
||||
|
||||
/// A queue to be consumed by [sentryUploader].
|
||||
static final sentryQueueControl = StreamController<Event>();
|
||||
|
||||
/// Whether sentry logging is currently enabled or not.
|
||||
static bool sentryIsEnabled;
|
||||
|
||||
static Future<void> sentryUploader() async {
|
||||
var client = SentryClient(dsn: config.sentryDsn);
|
||||
|
||||
await for (final event in sentryQueueControl.stream) {
|
||||
dynamic error;
|
||||
|
||||
try {
|
||||
var response = await client.capture(event: event);
|
||||
error = response.error;
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
if (error == null) continue;
|
||||
$.fine(
|
||||
"sentry upload failed; will retry after ${config.sentryRetryDelay} ($error)",
|
||||
);
|
||||
doSentryRetry(event);
|
||||
}
|
||||
}
|
||||
|
||||
static void doSentryRetry(Event event) async {
|
||||
await Future.delayed(config.sentryRetryDelay);
|
||||
sentryQueueControl.add(event);
|
||||
}
|
||||
|
||||
/// The log file currently in use.
|
||||
static File logFile;
|
||||
|
||||
/// Whether file logging is currently enabled or not.
|
||||
static bool fileIsEnabled;
|
||||
|
||||
static Future<void> setupLogDir() async {
|
||||
var dirPath = config.logDirPath;
|
||||
|
||||
// choose [logDir]
|
||||
if (dirPath.isEmpty) {
|
||||
var root = await getExternalStorageDirectory();
|
||||
dirPath = '${root.path}/logs';
|
||||
}
|
||||
|
||||
// create [logDir]
|
||||
var dir = Directory(dirPath);
|
||||
await dir.create(recursive: true);
|
||||
|
||||
var files = <File>[];
|
||||
var dates = <File, DateTime>{};
|
||||
|
||||
// collect all log files with valid names
|
||||
await for (final file in dir.list()) {
|
||||
try {
|
||||
var date = config.dateFmt.parse(basename(file.path));
|
||||
dates[file] = date;
|
||||
} on FormatException {}
|
||||
}
|
||||
|
||||
// delete old log files, if [maxLogFiles] is exceeded.
|
||||
if (files.length > config.maxLogFiles) {
|
||||
// sort files based on ascending order of date (older first)
|
||||
files.sort((a, b) => dates[a].compareTo(dates[b]));
|
||||
|
||||
var extra = files.length - config.maxLogFiles;
|
||||
var toDelete = files.sublist(0, extra);
|
||||
|
||||
for (var file in toDelete) {
|
||||
await file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
logFile = File("$dirPath/${config.dateFmt.format(DateTime.now())}.txt");
|
||||
}
|
||||
|
||||
/// Current app version, obtained from package_info plugin.
|
||||
///
|
||||
/// See: [getAppVersion]
|
||||
static String appVersion;
|
||||
|
||||
static Future<String> getAppVersion() async {
|
||||
var pkgInfo = await PackageInfo.fromPlatform();
|
||||
return "${pkgInfo.version}+${pkgInfo.buildNumber}";
|
||||
}
|
||||
}
|
61
thirdparty/super_logging/pubspec.yaml
vendored
Normal file
61
thirdparty/super_logging/pubspec.yaml
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
name: super_logging
|
||||
description: The usual dart logging module, but with superpowers! Let's you easily log to stdout, disk and sentry.io.
|
||||
version: 1.3.4
|
||||
author: Dev Aggarwal <devpxy@gmail.com>
|
||||
homepage: https://github.com/scientifichackers/super_logging
|
||||
|
||||
environment:
|
||||
sdk: ">=2.6.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
package_info_plus: ^0.5.0
|
||||
device_info: ^0.4.1+4
|
||||
logging: ^0.11.4
|
||||
sentry: ^3.0.1
|
||||
intl: ^0.16.1
|
||||
path: ^1.6.4
|
||||
path_provider: ^1.6.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
flutter:
|
||||
|
||||
# To add assets to your package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.io/assets-and-images/#from-packages
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.io/assets-and-images/#resolution-aware.
|
||||
|
||||
# To add custom fonts to your package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.io/custom-fonts/#from-packages
|
55
thirdparty/super_logging/test/test_string_chunked.dart
vendored
Normal file
55
thirdparty/super_logging/test/test_string_chunked.dart
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:super_logging/super_logging.dart';
|
||||
|
||||
var random = Random();
|
||||
|
||||
void main() {
|
||||
final chunkSize = SuperLogging.logChunkSize;
|
||||
|
||||
test('test with empty text', () {
|
||||
var text = randomText(0);
|
||||
|
||||
var actual = text.chunked(chunkSize).toList();
|
||||
var expected = [];
|
||||
|
||||
expect(expected, actual);
|
||||
});
|
||||
|
||||
test('test with length < chunk size', () {
|
||||
var text = randomText(chunkSize ~/ 2.5);
|
||||
|
||||
var actual = text.chunked(chunkSize).toList();
|
||||
var expected = [text];
|
||||
|
||||
expect(expected, actual);
|
||||
});
|
||||
|
||||
test('test with length = chunk size', () {
|
||||
var text = randomText(chunkSize);
|
||||
|
||||
var actual = text.chunked(chunkSize).toList();
|
||||
var expected = [text];
|
||||
|
||||
expect(expected, actual);
|
||||
});
|
||||
|
||||
test('test with length > chunk size', () {
|
||||
var text = randomText((chunkSize * 2.5).toInt());
|
||||
|
||||
var actual = text.chunked(chunkSize).toList();
|
||||
var expected = [
|
||||
text.substring(0, chunkSize),
|
||||
text.substring(chunkSize, chunkSize * 2),
|
||||
text.substring(chunkSize * 2)
|
||||
];
|
||||
|
||||
expect(expected, actual);
|
||||
});
|
||||
}
|
||||
|
||||
String randomText(int len) {
|
||||
var charCodes = List.generate(len, (index) => random.nextInt(0x10FFFF));
|
||||
return String.fromCharCodes(charCodes).substring(0, len);
|
||||
}
|
Loading…
Add table
Reference in a new issue