LCOV - code coverage report
Current view: top level - lib/src - forest.dart Hit Total Coverage
Test: lcov.info Lines: 111 114 97.4 %
Date: 2020-11-11 18:24:22

          Line data    Source code
       1             : import 'dart:async';
       2             : 
       3             : import 'package:async/async.dart';
       4             : import 'package:flutter/foundation.dart';
       5             : import 'package:logging/logging.dart';
       6             : import 'package:logging/logging.dart' show LogRecord;
       7             : import 'package:quiver/check.dart';
       8             : import 'package:synchronized/synchronized.dart';
       9             : import 'package:timber/src/analytics.dart';
      10             : 
      11             : import 'crashreport_tree.dart';
      12             : import 'log_tree.dart';
      13             : import 'tree.dart';
      14             : 
      15           3 : final _forestLogger = Logger('Forest');
      16             : 
      17             : class Forest extends Tree
      18             :     with LogTree, CrashReportTree, AnalyticsTree, UserAnalyticsTree {
      19             :   final _lock = Lock();
      20             :   final _memo = AsyncMemoizer();
      21             :   final FlutterExceptionHandler _exceptionHandler;
      22             : 
      23           1 :   Forest([this._exceptionHandler]);
      24             : 
      25             :   StreamSubscription<LogRecord> _subscription;
      26             : 
      27           1 :   Future<void> init() {
      28           3 :     return _memo.runOnce(() {
      29             :       // This captures errors reported by the Flutter framework.
      30           2 :       FlutterError.onError = _exceptionHandler ?? onFlutterError;
      31           5 :       _subscription = Logger.root.onRecord.listen((record) {
      32           1 :         performLog(record);
      33             :       });
      34             :     });
      35             :   }
      36             : 
      37             :   // Default Error Handler
      38           1 :   void onFlutterError(FlutterErrorDetails details) {
      39           1 :     if (isInDebugMode) {
      40             :       // In development mode simply print to console.
      41           1 :       FlutterError.dumpErrorToConsole(details);
      42             :     } else {
      43             :       // In production mode report to the application zone to report to
      44             :       // Forest.
      45           1 :       performReportFlutterError(details);
      46             :     }
      47             :   }
      48             : 
      49           1 :   @override
      50             :   void performLog(LogRecord record) {
      51           3 :     _logTrees.forEach((tree) {
      52           1 :       tree.performLog(record);
      53             :     });
      54             :   }
      55             : 
      56             :   /// Flutter Error 를 Report 합니다.
      57             :   /// ex: Crashlytics, Sentry
      58             :   @override
      59           1 :   Future<void> performReportError(error, stackTrace) async {
      60           3 :     _forestLogger.info('Caught error: $error');
      61             : 
      62             :     // Errors thrown in development mode are unlikely to be interesting. You can
      63             :     // check if you are running in dev mode using an assertion and omit sending
      64             :     // the report.
      65           1 :     if (isInDebugMode) {
      66             :       // 디버그 모드에서는 전체 stacktrace를 출력합니다.
      67           2 :       _forestLogger.info(stackTrace);
      68           2 :       _forestLogger.info('In dev mode. Not sending report to Sentry.io.');
      69             :       return;
      70             :     } else {
      71           2 :       _forestLogger.info('performReport');
      72             : 
      73           3 :       _crashReportTrees.forEach((tree) {
      74           1 :         tree.performReportError(error, stackTrace);
      75             :       });
      76             :     }
      77             :   }
      78             : 
      79             :   /// Flutter Error 를 Report 합니다.
      80             :   /// ex: Crashlytics, Sentry
      81           1 :   @override
      82             :   void performReportFlutterError(FlutterErrorDetails details) {
      83           4 :     _forestLogger.info('Caught error: ${details.exception}');
      84             : 
      85             :     // Errors thrown in development mode are unlikely to be interesting. You can
      86             :     // check if you are running in dev mode using an assertion and omit sending
      87             :     // the report.
      88           1 :     if (isInDebugMode) {
      89             :       // 디버그 모드에서는 전체 stacktrace를 출력합니다.
      90           3 :       _forestLogger.info(details.stack);
      91           2 :       _forestLogger.info('In dev mode. Not sending report to Sentry.io.');
      92             :       return;
      93             :     } else {
      94           2 :       _forestLogger.info('performReport');
      95             : 
      96           3 :       _crashReportTrees.forEach((tree) {
      97           1 :         tree.performReportFlutterError(details);
      98             :       });
      99             :     }
     100             :   }
     101             : 
     102             :   final _trees = <Tree>[];
     103             : 
     104           3 :   Iterable<LogTree> get _logTrees => _trees.whereType<LogTree>();
     105             : 
     106           1 :   Iterable<CrashReportTree> get _crashReportTrees =>
     107           2 :       _trees.whereType<CrashReportTree>();
     108             : 
     109           1 :   Iterable<AnalyticsTree> get _analyticsTrees =>
     110           2 :       _trees.whereType<AnalyticsTree>();
     111             : 
     112           1 :   Iterable<UserAnalyticsTree> get _userAnalyticsTrees =>
     113           2 :       _trees.whereType<UserAnalyticsTree>();
     114             : 
     115             :   /// Add a new logging tree.
     116           1 :   void plant(Tree tree) {
     117           2 :     checkArgument(tree != this);
     118           5 :     _lock.synchronized(() => _trees.add(tree));
     119             :   }
     120             : 
     121             :   /// Add a new logging tree.
     122           1 :   void plantAll(Iterable<Tree> trees) {
     123           2 :     for (var tree in trees) {
     124           1 :       checkNotNull(tree);
     125           2 :       checkArgument(tree != this, message: 'Cannot plant Timber into itself.');
     126             :     }
     127           5 :     _lock.synchronized(() => _trees.addAll(trees));
     128             :   }
     129             : 
     130             :   /// Remove a planted tree.
     131           1 :   void uproot(Tree tree) {
     132           5 :     _lock.synchronized(() => _trees.remove(tree));
     133             :   }
     134             : 
     135             :   /// Remove all planted tree.
     136           1 :   void uprootAll() {
     137           5 :     _lock.synchronized(() => _trees.clear());
     138             :   }
     139             : 
     140             :   /// Return a copy of all planted [trees][Tree].
     141           1 :   Future<List<Tree>> get forest {
     142           5 :     return _lock.synchronized(() => List.unmodifiable(_trees));
     143             :   }
     144             : 
     145           3 :   int get treeCount => _trees.length;
     146             : 
     147             :   /// Override the level for this particular [Logger] and its children.
     148           1 :   set level(Level value) {
     149           2 :     Logger.root.level = value;
     150             :   }
     151             : 
     152           3 :   Level get level => Logger.root.level;
     153             : 
     154           1 :   @override
     155             :   void dispose() {
     156           3 :     _lock.synchronized(() {
     157           3 :       _trees.forEach((tree) {
     158           1 :         tree.dispose();
     159             :       });
     160           2 :       _trees.clear();
     161             :     });
     162           1 :     _subscription?.cancel();
     163           1 :     _subscription = null;
     164             :   }
     165             : 
     166           1 :   @override
     167             :   bool isSupportedEventName(String name) {
     168             :     return true;
     169             :   }
     170             : 
     171           1 :   @override
     172             :   Set<Type> get supportedTypes {
     173             :     var set = <Type>{};
     174           3 :     _analyticsTrees.forEach((tree) {
     175           2 :       set.addAll(tree.supportedTypes);
     176             :     });
     177             :     return set;
     178             :   }
     179             : 
     180           1 :   @override
     181             :   bool isSupportedType(value) {
     182           4 :     return _analyticsTrees.any((element) => element.isSupportedType(value));
     183             :   }
     184             : 
     185           1 :   @override
     186             :   Future<void> performLogEvent(
     187             :       {@required String name, Map<String, dynamic> parameters}) {
     188           6 :     _analyticsTrees.where((tree) => isSupportedEventName(name)).forEach((tree) {
     189           1 :       tree.performLogEvent(name: name, parameters: parameters);
     190             :     });
     191             :   }
     192             : 
     193             :   @override
     194           1 :   Future<void> setUserProperty(String name, value) async {
     195           3 :     _userAnalyticsTrees.forEach((tree) {
     196           1 :       tree.setUserProperty(name, value);
     197             :     });
     198             :   }
     199             : 
     200             :   /// userId 설정
     201             :   @override
     202           1 :   Future<void> setUserId(String id) async {
     203           3 :     _userAnalyticsTrees.forEach((tree) {
     204           1 :       tree.setUserId(id);
     205             :     });
     206             :   }
     207             : 
     208             :   /// email 설정
     209             :   @override
     210           1 :   Future<void> setEmail(String email) async {
     211           3 :     _userAnalyticsTrees.forEach((tree) {
     212           1 :       tree.setEmail(email);
     213             :     });
     214             :   }
     215             : 
     216             :   /// 전화번호 설정
     217             :   @override
     218           1 :   Future<void> setPhone(String phone) async {
     219           3 :     _userAnalyticsTrees.forEach((tree) {
     220           1 :       tree.setPhone(phone);
     221             :     });
     222             :   }
     223             : 
     224             :   /// uid 설정
     225             :   @override
     226           1 :   Future<void> setUid(String uid) async {
     227           3 :     _userAnalyticsTrees.forEach((tree) {
     228           1 :       tree.setUid(uid);
     229             :     });
     230             :   }
     231             : 
     232             :   @override
     233           1 :   Future<void> union(Map<String, List<dynamic>> properties) async {
     234           3 :     _userAnalyticsTrees.forEach((tree) {
     235           1 :       tree.union(properties);
     236             :     });
     237             :   }
     238             : 
     239             :   @override
     240           1 :   Future<void> increment(Map<String, num> properties) async {
     241           3 :     _userAnalyticsTrees.forEach((tree) {
     242           1 :       tree.increment(properties);
     243             :     });
     244             :   }
     245             : 
     246             :   @override
     247           1 :   Future<void> setOnce(Map<String, dynamic> properties) async {
     248           3 :     _userAnalyticsTrees.forEach((tree) {
     249           1 :       tree.setOnce(properties);
     250             :     });
     251             :   }
     252             : 
     253             :   @override
     254           1 :   Future<void> setUserName(value) async {
     255           3 :     _userAnalyticsTrees.forEach((tree) {
     256           1 :       tree.setUserName(value);
     257             :     });
     258             :   }
     259             : 
     260             :   @override
     261           1 :   Future<void> reset() async {
     262           3 :     _userAnalyticsTrees.forEach((tree) {
     263           1 :       tree.reset();
     264             :     });
     265           3 :     _analyticsTrees.forEach((tree) {
     266           1 :       tree.reset();
     267             :     });
     268             :   }
     269             : 
     270             :   @override
     271           1 :   Future<void> flush() async {
     272           3 :     _userAnalyticsTrees.forEach((tree) {
     273           1 :       tree.flush();
     274             :     });
     275           3 :     _analyticsTrees.forEach((tree) {
     276           1 :       tree.flush();
     277             :     });
     278             :   }
     279             : 
     280             :   @override
     281           0 :   Future<void> setCurrentScreen(
     282             :       {String screenName, String screenClassOverride = 'Flutter'}) async {
     283           0 :     _analyticsTrees.forEach((tree) {
     284           0 :       tree.setCurrentScreen(
     285             :           screenName: screenName, screenClassOverride: screenClassOverride);
     286             :     });
     287             :   }
     288             : 
     289             :   @override
     290           1 :   Future<void> timingEvent(String name) async {
     291           3 :     _analyticsTrees.forEach((tree) {
     292           1 :       tree.timingEvent(name);
     293             :     });
     294             :   }
     295             : }

Generated by: LCOV version 1.14