| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:io'; |
| |
| import 'package:logging/logging.dart'; |
| |
| import '../internal/_fuchsia_log_writer.dart'; |
| import '../internal/_log_writer.dart'; |
| import '../internal/_stdout_log_writer.dart'; |
| |
| const _warningMessage = |
| '\n========================== WARNING ================================\n' |
| '| log called before setupLogger() was called. |\n' |
| '| All log message will still be sent to the fuchsia system logger |\n' |
| '| but some log messages may be missed if they were emitted by |\n' |
| '| third_party libraries. To avoid this make sure you call |\n' |
| '| setupLogger() in your main method before any other calls. |\n' |
| '===================================================================\n'; |
| |
| /// The logger instance in which logs will be written. |
| /// |
| /// This logger will connect to the Fuchsia system logger when running |
| /// on a Fuchsia device and will write to stdout when not. |
| /// When running on a Fuchsia device logs can be viewed by running |
| /// `fx syslog`. |
| Logger log = () { |
| _connectToLogWriterIfNeeded(); |
| print(_warningMessage); |
| |
| return Logger.root; |
| }(); |
| |
| LogWriter _logWriter; |
| |
| /// Sets up the default logger for the current Dart application. |
| /// |
| /// Every Dart application should call this [setupLogger] function in their main |
| /// before calling the actual log statements. |
| /// |
| /// The provided [name] will be used for displaying the scope, and this name |
| /// will default to the last segment (i.e. basename) of the application url. |
| /// |
| /// If [level] is provided, only the log messages of which level is greater than |
| /// equal to the provided [level] will be shown. If not provided, it defaults to |
| /// [Level.ALL]. |
| /// |
| /// If [globalTags] is provided, these tags will be added to each message logged |
| /// via this logger. The logger can accept 5 global tags, however, one of those |
| /// tags is reserved for the logger name and one is reserved for the code |
| /// location if it is requested. The logger will drop any tags that are over |
| /// this limit. |
| /// |
| /// By default, the caller code location is automatically added in checked mode |
| /// and not in production mode, because it is relatively expensive to calculate |
| /// the code location. If [forceShowCodeLocation] is set to true, the location |
| /// will be added in production mode as well. |
| void setupLogger({ |
| String name, |
| Level level, |
| List<String> globalTags, |
| bool forceShowCodeLocation, |
| }) { |
| // set the log variable to the root logger and set the level to that |
| // specified by level. We do this so subsequent calls to the log method |
| // will not run the default setup method. |
| log = Logger.root..level = level ?? Level.ALL; |
| |
| // connect to the logger writer here. If log has already been called this |
| // method will be a noop. At this point, _logWriter will not be null |
| _connectToLogWriterIfNeeded(); |
| |
| // We need to provide a name for the logger in the form of a tag because |
| // we are not using hierarchical logging. |
| // Tags get appended to each log statement. We put the name, if present |
| // as the first tag so it makes it easier to identify. |
| // We remove any null values before sending them to the logger |
| final List<String> tags = [ |
| name ?? |
| Platform.script?.pathSegments |
| ?.lastWhere((_) => true, orElse: () => null) |
| ] |
| ..addAll(globalTags ?? const []) |
| ..removeWhere((t) => t == null || t.isEmpty); |
| |
| bool inCheckedMode = false; |
| assert(() { |
| inCheckedMode = true; |
| return true; |
| }()); |
| |
| _logWriter |
| ..globalTags = tags |
| ..forceShowCodeLocation = forceShowCodeLocation ?? inCheckedMode; |
| } |
| |
| void _connectToLogWriterIfNeeded({ |
| String name, |
| Level level, |
| }) { |
| if (_logWriter != null) { |
| // we have already connected so there is nothing we need to do |
| return; |
| } |
| |
| if (Platform.isFuchsia) { |
| _logWriter = FuchsiaLogWriter(logger: Logger.root); |
| } else { |
| _logWriter = StdoutLogWriter(logger: Logger.root); |
| } |
| } |