This repository was archived by the owner on Feb 25, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6k
[et] Adds a logger #50693
Merged
Merged
[et] Adds a logger #50693
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| // Copyright 2013 The Flutter 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:async' show runZoned; | ||
| import 'dart:io' as io show | ||
| IOSink, | ||
| stderr, | ||
| stdout; | ||
|
|
||
| import 'package:logging/logging.dart' as log; | ||
| import 'package:meta/meta.dart'; | ||
|
|
||
| // This is where a flutter_tool style progress spinner, color output, | ||
| // ascii art, terminal control for clearing lines or the whole screen, etc. | ||
| // can go. We can just add more methods to Logger using the flutter_tool's | ||
| // Logger as a guide: | ||
| // | ||
| // https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/base/logger.dart#L422 | ||
|
|
||
| /// A simplified wrapper around the [Logger] from package:logging. | ||
| /// | ||
| /// The default log level is [Logger.status]. A --quiet flag might change it to | ||
| /// [Logger.warning] or [Logger.error]. A --verbose flag might change it to | ||
| /// [Logger.info]. | ||
| /// | ||
| /// Log messages at [Logger.warning] and higher will be written to stderr, and | ||
| /// to stdout otherwise. [Logger.test] records all log messages to a buffer, | ||
| /// which can be inspected by unit tetss. | ||
| class Logger { | ||
| /// Constructs a logger for use in the tool. | ||
| Logger() : _logger = log.Logger.detached('et') { | ||
| _logger.level = statusLevel; | ||
| _logger.onRecord.listen(_handler); | ||
| _setupIoSink(io.stderr); | ||
| _setupIoSink(io.stdout); | ||
| } | ||
|
|
||
| /// A logger for tests. | ||
| @visibleForTesting | ||
| Logger.test() : _logger = log.Logger.detached('et') { | ||
| _logger.level = statusLevel; | ||
| _logger.onRecord.listen((log.LogRecord r) => _testLogs.add(r)); | ||
| } | ||
|
|
||
| /// The logging level for error messages. These go to stderr. | ||
| static const log.Level errorLevel = log.Level('ERROR', 100); | ||
|
|
||
| /// The logging level for warning messages. These go to stderr. | ||
| static const log.Level warningLevel = log.Level('WARNING', 75); | ||
|
|
||
| /// The logging level for normal status messages. These go to stdout. | ||
| static const log.Level statusLevel = log.Level('STATUS', 25); | ||
|
|
||
| /// The logging level for verbose informational messages. These go to stdout. | ||
| static const log.Level infoLevel = log.Level('INFO', 10); | ||
|
|
||
| static void _handler(log.LogRecord r) { | ||
| final io.IOSink sink = r.level >= warningLevel ? io.stderr : io.stdout; | ||
| final String prefix = r.level >= warningLevel | ||
| ? '[${r.time}] ${r.level}: ' | ||
| : ''; | ||
| _ioSinkWrite(sink, '$prefix${r.message}'); | ||
| } | ||
|
|
||
| // Status of the global io.stderr and io.stdout is shared across all | ||
| // Logger instances. | ||
| static bool _stdioDone = false; | ||
|
|
||
| // stdout and stderr might already be closed, and when not already closed, | ||
| // writing can still fail by throwing either a sync or async exception. | ||
| // This function handles all three cases. | ||
| static void _ioSinkWrite(io.IOSink sink, String message) { | ||
| if (_stdioDone) { | ||
| return; | ||
| } | ||
| runZoned<void>(() { | ||
| try { | ||
| sink.writeln(message); | ||
| } catch (_) { // ignore: avoid_catches_without_on_clauses | ||
| _stdioDone = true; | ||
| } | ||
| }, onError: (Object e, StackTrace s) { | ||
| _stdioDone = true; | ||
| }); | ||
| } | ||
|
|
||
| static void _setupIoSink(io.IOSink sink) { | ||
| sink.done.then( | ||
| (void _) { _stdioDone = true; }, | ||
| onError: (Object err, StackTrace st) { _stdioDone = true; }, | ||
| ); | ||
| } | ||
|
|
||
| final log.Logger _logger; | ||
| final List<log.LogRecord> _testLogs = <log.LogRecord>[]; | ||
|
|
||
| /// Get the current logging level. | ||
| log.Level get level => _logger.level; | ||
|
|
||
| /// Set the current logging level. | ||
| set level(log.Level l) { | ||
| _logger.level = l; | ||
| } | ||
|
|
||
| /// Record a log message at level [Logger.error]. | ||
| void error(Object? message, {int indent = 0}) { | ||
| _emitLog(errorLevel, message, indent); | ||
| } | ||
|
|
||
| /// Record a log message at level [Logger.warning]. | ||
| void warning(Object? message, {int indent = 0}) { | ||
| _emitLog(warningLevel, message, indent); | ||
| } | ||
|
|
||
| /// Record a log message at level [Logger.warning]. | ||
| void status(Object? message, {int indent = 0}) { | ||
| _emitLog(statusLevel, message, indent); | ||
| } | ||
|
|
||
| /// Record a log message at level [Logger.info]. | ||
| void info(Object? message, {int indent = 0}) { | ||
| _emitLog(infoLevel, message, indent); | ||
| } | ||
|
|
||
| void _emitLog(log.Level level, Object? message, int indent) { | ||
| final String m = '${' ' * indent}$message'; | ||
| _logger.log(level, m); | ||
| } | ||
|
|
||
| /// In a [Logger] constructed by [Logger.test], this list will contain all of | ||
| /// the [LogRecord]s emitted by the test. | ||
| @visibleForTesting | ||
| List<log.LogRecord> get testLogs => _testLogs; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| // Copyright 2013 The Flutter 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 'package:engine_tool/src/logger.dart'; | ||
| import 'package:litetest/litetest.dart'; | ||
| import 'package:logging/logging.dart' as log; | ||
|
|
||
| void main() { | ||
| List<String> stringsFromLogs(List<log.LogRecord> logs) { | ||
| return logs.map((log.LogRecord r) => r.message).toList(); | ||
| } | ||
|
|
||
| test('Setting the level works', () { | ||
| final Logger logger = Logger.test(); | ||
| logger.level = Logger.infoLevel; | ||
| expect(logger.level, equals(Logger.infoLevel)); | ||
| }); | ||
|
|
||
| test('error messages are recorded at the default log level', () { | ||
| final Logger logger = Logger.test(); | ||
| logger.error('Error'); | ||
| expect(stringsFromLogs(logger.testLogs), equals(<String>['Error'])); | ||
| }); | ||
|
|
||
| test('warning messages are recorded at the default log level', () { | ||
| final Logger logger = Logger.test(); | ||
| logger.warning('Warning'); | ||
| expect(stringsFromLogs(logger.testLogs), equals(<String>['Warning'])); | ||
| }); | ||
|
|
||
| test('status messages are recorded at the default log level', () { | ||
| final Logger logger = Logger.test(); | ||
| logger.status('Status'); | ||
| expect(stringsFromLogs(logger.testLogs), equals(<String>['Status'])); | ||
| }); | ||
|
|
||
| test('info messages are not recorded at the default log level', () { | ||
| final Logger logger = Logger.test(); | ||
| logger.info('info'); | ||
| expect(stringsFromLogs(logger.testLogs), equals(<String>[])); | ||
| }); | ||
|
|
||
| test('info messages are recorded at the infoLevel log level', () { | ||
| final Logger logger = Logger.test(); | ||
| logger.level = Logger.infoLevel; | ||
| logger.info('info'); | ||
| expect(stringsFromLogs(logger.testLogs), equals(<String>['info'])); | ||
| }); | ||
|
|
||
| test('indent indents the message', () { | ||
| final Logger logger = Logger.test(); | ||
| logger.status('Status', indent: 1); | ||
| expect(stringsFromLogs(logger.testLogs), equals(<String>[' Status'])); | ||
| }); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.