Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(395)

Side by Side Diff: pkg/code_transformers/lib/messages/build_logger.dart

Issue 513023002: Step one towards stable error messages with details: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698