OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library polymer.src.build.wrapped_logger; | 5 library code_transformers.messages.messages_logger; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert' show JSON; |
9 | 9 |
10 import 'package:barback/barback.dart'; | 10 import 'package:barback/barback.dart'; |
11 import 'package:source_span/source_span.dart'; | 11 import 'package:source_span/source_span.dart'; |
12 | 12 |
13 import 'common.dart' as common; | 13 import 'messages.dart' show Message, MessageId, BuildLogEntry, LogEntryTable; |
14 | 14 |
15 /// A simple class to wrap one TransformLogger with another one that writes all | 15 /// A [TransformLogger] used to track error and warning messages produced during |
16 /// logs to a file and then forwards the calls to the child. | 16 /// a build. |
17 class WrappedLogger implements TransformLogger { | 17 /// |
18 Transform _transform; | 18 /// This logger records all messages that were log and then forwards |
jakemac
2014/09/03 17:20:41
s/log/logged
Siggi Cherem (dart-lang)
2014/09/04 02:32:13
Done.
| |
19 List<Map> _logs = new List<Map>(); | 19 /// the calls to an underlying [TransformLogger]. The internal records support |
20 /// serializing the errors and emiting them to an asset (so they can be | |
21 /// presented to the user in a web-based client), clustering similar messages | |
22 /// together, sorting messages in order of importance, etc. | |
23 /// | |
24 /// The logger also supports reporting error messages as warnings. Barback makes | |
25 /// error messages stop the transformation process, which sometimes can surprise | |
26 /// users. Turning errors into warnings is especially useful when used within | |
27 /// `pub serve`, where we would like the transformation to continue as far as it | |
28 /// can. When this flag is turned on, the level is still recorded as an error, | |
29 /// so a web client UI can still highlight their importance. | |
30 // TODO(sigmund): also cluster messages when they are reported on the | |
31 // command-line. | |
32 class BuildLogger implements TransformLogger { | |
33 /// Underling transform that is currently active. | |
34 final Transform _transform; | |
20 | 35 |
21 bool convertErrorsToWarnings; | 36 /// Logs created during the current transform. |
37 final LogEntryTable _logs = new LogEntryTable(); | |
22 | 38 |
23 WrappedLogger(this._transform, {this.convertErrorsToWarnings: false}); | 39 /// Whether to use `warning` or `error` when forwarding error messages to the |
40 /// underlying logger in `_transform.logger`. | |
41 final bool convertErrorsToWarnings; | |
24 | 42 |
25 void info(String message, {AssetId asset, SourceSpan span}) { | 43 BuildLogger(this._transform, {this.convertErrorsToWarnings: false}); |
26 _transform.logger.info(message, asset: asset, span: span); | 44 |
27 _addLog(asset, LogLevel.INFO, message, span); | 45 /// Records a message at the fine level, [msg] can be a [String] or [Message]. |
jakemac
2014/09/03 17:20:41
Technically it doesn't have to be a String, it can
Siggi Cherem (dart-lang)
2014/09/04 02:32:13
Good point :), rephrased
| |
46 void fine(msg, {AssetId asset, SourceSpan span}) { | |
47 var snippet = msg is Message ? msg.snippet : '$msg'; | |
jakemac
2014/09/03 17:20:41
I don't think either of these variables are really
Siggi Cherem (dart-lang)
2014/09/04 02:32:13
nice, done.
| |
48 var message = msg is Message ? msg : new Message( | |
49 MessageId.NOT_SPECIFIED, snippet); | |
50 _transform.logger.fine(snippet, asset: asset, span: span); | |
51 _logs.add(new BuildLogEntry(message, span, LogLevel.FINE.name)); | |
28 } | 52 } |
29 | 53 |
30 void fine(String message, {AssetId asset, SourceSpan span}) { | 54 /// Records a message at the info level, [msg] can be a [String] or [Message]. |
31 _transform.logger.fine(message, asset: asset, span: span); | 55 void info(msg, {AssetId asset, SourceSpan span}) { |
32 _addLog(asset, LogLevel.FINE, message, span); | 56 var snippet = msg is Message ? msg.snippet : '$msg'; |
57 var message = msg is Message ? msg : new Message( | |
58 MessageId.NOT_SPECIFIED, snippet); | |
59 _transform.logger.info(snippet, asset: asset, span: span); | |
60 _logs.add(new BuildLogEntry(message, span, LogLevel.INFO.name)); | |
33 } | 61 } |
34 | 62 |
35 void warning(String message, {AssetId asset, SourceSpan span}) { | 63 /// Records a warning message, [msg] can be a [String] or [Message]. |
36 _transform.logger.warning(message, asset: asset, span: span); | 64 void warning(msg, {AssetId asset, SourceSpan span}) { |
37 _addLog(asset, LogLevel.WARNING, message, span); | 65 var snippet = msg is Message ? msg.snippet : '$msg'; |
66 var message = msg is Message ? msg : new Message( | |
67 MessageId.NOT_SPECIFIED, snippet); | |
68 _transform.logger.warning(snippet, asset: asset, span: span); | |
69 _logs.add(new BuildLogEntry(message, span, LogLevel.WARNING.name)); | |
38 } | 70 } |
39 | 71 |
40 void error(String message, {AssetId asset, SourceSpan span}) { | 72 /// Records an error message, [msg] can be a [String] or [Message]. |
73 void error(msg, {AssetId asset, SourceSpan span}) { | |
74 var snippet = msg is Message ? msg.snippet : '$msg'; | |
75 var message = msg is Message ? msg : new Message( | |
76 MessageId.NOT_SPECIFIED, snippet); | |
41 if (convertErrorsToWarnings) { | 77 if (convertErrorsToWarnings) { |
42 _transform.logger.warning(message, asset: asset, span: span); | 78 _transform.logger.warning(snippet, asset: asset, span: span); |
43 } else { | 79 } else { |
44 _transform.logger.error(message, asset: asset, span: span); | 80 _transform.logger.error(snippet, asset: asset, span: span); |
45 } | 81 } |
46 _addLog(asset, LogLevel.ERROR, message, span); | 82 _logs.add(new BuildLogEntry(message, span, LogLevel.ERROR.name)); |
47 } | 83 } |
48 | 84 |
49 /// Outputs the log data to a JSON serialized file. | 85 /// Outputs the log data to a JSON serialized file. |
50 Future writeOutput() { | 86 Future writeOutput() { |
51 return getNextLogAssetPath().then((path) { | 87 return _getNextLogAssetPath().then((path) { |
52 _transform.addOutput(new Asset.fromString(path, JSON.encode(_logs))); | 88 _transform.addOutput(new Asset.fromString(path, |
89 JSON.encode(_logs.toJson()))); | |
jakemac
2014/09/03 17:20:41
I thought JSON.encode will automatically call toJs
Siggi Cherem (dart-lang)
2014/09/04 02:32:13
done.
| |
53 }); | 90 }); |
54 } | 91 } |
55 | 92 |
56 // Each phase outputs a new log file with an incrementing # appended, this | 93 // Each phase outputs a new log file with an incrementing # appended, this |
57 // figures out the next # to use. | 94 // figures out the next # to use. |
58 Future<String> getNextLogAssetPath([int nextNumber = 1]) { | 95 Future<String> _getNextLogAssetPath([int nextNumber = 1]) { |
59 var nextAssetPath = _transform.primaryInput.id.addExtension( | 96 var nextAssetPath = _transform.primaryInput.id.addExtension( |
60 '${common.LOG_EXTENSION}.$nextNumber'); | 97 '${LOG_EXTENSION}.$nextNumber'); |
61 return _transform.hasInput(nextAssetPath).then((exists) { | 98 return _transform.hasInput(nextAssetPath).then((exists) { |
62 if (!exists) return nextAssetPath; | 99 if (!exists) return nextAssetPath; |
63 return getNextLogAssetPath(++nextNumber); | 100 return _getNextLogAssetPath(++nextNumber); |
64 }); | 101 }); |
65 } | 102 } |
66 | 103 |
67 // Reads all log files for an Asset into [logs]. | 104 // Reads all log files for an Asset into [logs]. |
68 static Future _readLogFilesForAsset( | 105 static Future _readLogFilesForAsset(AssetId id, Transform transform, |
69 AssetId id, Transform transform, List<Map> logs, [nextNumber = 1]) { | 106 LogEntryTable entries, [nextNumber = 1]) { |
70 var nextAssetPath = id.addExtension('${common.LOG_EXTENSION}.$nextNumber'); | 107 var nextAssetPath = id.addExtension('${LOG_EXTENSION}.$nextNumber'); |
71 return transform.hasInput(nextAssetPath).then((exists) { | 108 return transform.hasInput(nextAssetPath).then((exists) { |
72 if (!exists) return null; | 109 if (!exists) return null; |
73 return transform.readInputAsString(nextAssetPath).then((data) { | 110 return transform.readInputAsString(nextAssetPath).then((data) { |
74 logs.addAll(JSON.decode(data)); | 111 entries.addAll(new LogEntryTable.fromJson(JSON.decode(data))); |
75 return _readLogFilesForAsset(id, transform, logs, ++nextNumber); | 112 return _readLogFilesForAsset(id, transform, entries, ++nextNumber); |
76 }); | 113 }); |
77 }); | 114 }); |
78 } | 115 } |
79 | 116 |
80 // Combines all existing ._buildLogs.* files into a single ._buildLogs file. | 117 // Combines all existing ._buildLogs.* files into a single ._buildLogs file. |
81 static Future combineLogFiles(Transform transform) { | 118 static Future combineLogFiles(Transform transform) { |
82 var logs = new List<Map>(); | 119 var entries = new LogEntryTable(); |
83 var id = transform.primaryInput.id; | 120 var id = transform.primaryInput.id; |
84 return _readLogFilesForAsset(id, transform, logs).then((_) { | 121 return _readLogFilesForAsset(id, transform, entries).then((_) { |
85 return transform.addOutput(new Asset.fromString( | 122 return transform.addOutput(new Asset.fromString( |
86 id.addExtension(common.LOG_EXTENSION), | 123 id.addExtension(LOG_EXTENSION), |
87 JSON.encode(logs))); | 124 JSON.encode(entries.toJson()))); |
88 }); | 125 }); |
89 } | 126 } |
90 | 127 |
91 // Reads all logs for an asset and adds them to this loggers log output. | 128 // Reads all logs for an asset and adds them to this loggers log output. |
92 Future addLogFilesFromAsset(AssetId id, [int nextNumber = 1]) { | 129 Future addLogFilesFromAsset(AssetId id, [int nextNumber = 1]) { |
93 return _readLogFilesForAsset(id, _transform, _logs); | 130 return _readLogFilesForAsset(id, _transform, _logs); |
94 } | 131 } |
132 } | |
95 | 133 |
96 void _addLog(AssetId assetId, LogLevel level, String message, | 134 /// Extension used for assets that contained serialized logs. |
97 SourceSpan span) { | 135 const String LOG_EXTENSION = '._buildLogs'; |
98 var data = { | |
99 'level': level.name, | |
100 'message': const HtmlEscape().convert(message), | |
101 }; | |
102 if (assetId != null) { | |
103 data['assetId'] = { | |
104 'package': assetId.package, | |
105 'path': assetId.path, | |
106 }; | |
107 } | |
108 if (span != null) { | |
109 data['span'] = { | |
110 'location': span.start.toolString, | |
111 'text': new HtmlEscape().convert(span.text), | |
112 }; | |
113 } | |
114 _logs.add(data); | |
115 } | |
116 } | |
OLD | NEW |