Skip to content

Commit ca4c5eb

Browse files
authored
Improved logging (#4011)
* Improved logging. * Address review comments. Time AnalysisDriverModel.performResolve time as `resolve`. * Move log of server status before build. * Remove unused import. * Address review comments. * Fix test.
1 parent 864e7c4 commit ca4c5eb

File tree

100 files changed

+4024
-2134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+4024
-2134
lines changed

_test/test/build_integration_test.dart

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ library;
88
import 'dart:io';
99

1010
import 'package:build_runner/src/build_script_generate/build_script_generate.dart';
11-
import 'package:build_runner_core/src/util/constants.dart';
11+
import 'package:build_runner_core/build_runner_core.dart';
1212
import 'package:path/path.dart' as p;
1313
import 'package:test/test.dart';
1414

@@ -54,10 +54,10 @@ void main() {
5454

5555
test('rebuilds if the input file changes and not otherwise', () async {
5656
var result = await runBuild();
57-
expect(result.stdout, contains('with 0 outputs'));
57+
expect(result.stdout, contains('wrote 0 outputs'));
5858
await replaceAllInFile('lib/hello.txt', 'hello', 'goodbye');
5959
result = await runBuild();
60-
expect(result.stdout, contains('with 1 outputs'));
60+
expect(result.stdout, contains('wrote 1 output'));
6161
var content = await readGeneratedFileAsString('_test/lib/hello.txt.post');
6262
expect(content, contains('goodbye'));
6363
});
@@ -70,7 +70,7 @@ void main() {
7070
);
7171

7272
expect(result.exitCode, isNot(0));
73-
expect(result.stdout, contains('Failed to precompile build script'));
73+
expect(result.stdout, contains('Failed to compile build script'));
7474
expect(
7575
result.stdout,
7676
contains('Unknown experiment: fake-experiment'),
@@ -134,14 +134,13 @@ void main() {
134134
expect(
135135
(nextBuild.stdout as String).split('\n'),
136136
containsAllInOrder([
137-
contains('Generating build script'),
137+
contains('Generating the build script'),
138+
contains('Compiling the build script.'),
139+
contains('Creating the asset graph.'),
138140
contains(
139-
'Invalidated precompiled build script due to missing asset '
140-
'graph.',
141+
'Building, full build because there is no valid asset graph.',
141142
),
142-
contains('Precompiling build script'),
143-
contains('Building new asset graph.'),
144-
contains('Succeeded after'),
143+
contains(BuildLog.successPattern),
145144
]),
146145
);
147146
});

_test/test/common/utils.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'dart:convert';
77
import 'dart:io';
88
import 'dart:isolate';
99

10+
import 'package:build_runner_core/build_runner_core.dart';
1011
import 'package:path/path.dart' as p;
1112
import 'package:test/test.dart';
1213
import 'package:test_process/test_process.dart';
@@ -155,11 +156,15 @@ Future<void> _resetGitClient() async {
155156
}
156157

157158
Future<void> get nextSuccessfulBuild async {
158-
await _stdOutLines!.firstWhere((line) => line.contains('Succeeded after'));
159+
await _stdOutLines!.firstWhere(
160+
(line) => line.contains(BuildLog.successPattern),
161+
);
159162
}
160163

161164
Future<void> get nextFailedBuild async {
162-
await _stdOutLines!.firstWhere((line) => line.contains('Failed after'));
165+
await _stdOutLines!.firstWhere(
166+
(line) => line.contains(BuildLog.failurePattern),
167+
);
163168
}
164169

165170
Future<String> nextStdOutLine(String message) =>

_test/test/goldens/generated_build_script.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// @dart=3.6
22
// ignore_for_file: directives_ordering
3+
// build_runner >=2.4.16
34
// ignore_for_file: no_leading_underscores_for_library_prefixes
45
import 'package:build_runner_core/build_runner_core.dart' as _i1;
56
import 'package:provides_builder/builders.dart' as _i2;

_test_common/lib/test_environment.dart

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import 'dart:async';
66

77
import 'package:build/build.dart';
88
import 'package:build_runner_core/build_runner_core.dart';
9-
import 'package:logging/logging.dart';
109

1110
import 'common.dart';
1211

@@ -32,8 +31,6 @@ class TestBuildEnvironment implements BuildEnvironment {
3231
/// [prompt].
3332
final bool throwOnPrompt;
3433

35-
final logRecords = <LogRecord>[];
36-
3734
/// The next response for calls to [prompt]. Must be set before calling
3835
/// [prompt].
3936
set nextPromptResponse(int next) {
@@ -48,9 +45,6 @@ class TestBuildEnvironment implements BuildEnvironment {
4845
this.throwOnPrompt = false,
4946
}) : _readerWriter = readerWriter ?? TestReaderWriter();
5047

51-
@override
52-
void onLog(LogRecord record) => logRecords.add(record);
53-
5448
/// Prompt the user for input.
5549
///
5650
/// The message and choices are displayed to the user and the index of the
@@ -67,17 +61,14 @@ class TestBuildEnvironment implements BuildEnvironment {
6761
}
6862

6963
@override
70-
BuildEnvironment copyWith({
71-
void Function(LogRecord)? onLogOverride,
72-
RunnerAssetWriter? writer,
73-
AssetReader? reader,
74-
}) => TestBuildEnvironment(
75-
readerWriter:
76-
(writer as TestReaderWriter?) ??
77-
(reader as TestReaderWriter?) ??
78-
_readerWriter,
79-
throwOnPrompt: throwOnPrompt,
80-
);
64+
BuildEnvironment copyWith({RunnerAssetWriter? writer, AssetReader? reader}) =>
65+
TestBuildEnvironment(
66+
readerWriter:
67+
(writer as TestReaderWriter?) ??
68+
(reader as TestReaderWriter?) ??
69+
_readerWriter,
70+
throwOnPrompt: throwOnPrompt,
71+
);
8172

8273
@override
8374
Future<BuildResult> finalizeBuild(

_test_common/lib/test_phases.dart

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ void _printOnFailure(LogRecord record) {
5252
///
5353
/// [status] optionally indicates the desired outcome.
5454
///
55-
/// [logLevel] sets the builder log level and [onLog] can optionally capture
56-
/// build log messages.
55+
/// [onLog] can optionally capture log messages.
5756
///
5857
/// Example:
5958
///
@@ -80,7 +79,6 @@ Future<TestBuildersResult> testPhases(
8079
PackageGraph? packageGraph,
8180
BuildStatus status = BuildStatus.success,
8281
Map<String, BuildConfig>? overrideBuildConfig,
83-
Level? logLevel,
8482
// A better way to "silence" logging than setting logLevel to OFF.
8583
void Function(LogRecord record) onLog = _printOnFailure,
8684
bool checkBuildStatus = true,
@@ -141,15 +139,14 @@ Future<TestBuildersResult> testPhases(
141139
packageGraph,
142140
reader: readerWriter,
143141
writer: readerWriter,
144-
onLogOverride: onLog,
145-
);
146-
var logSubscription = LogSubscription(
147-
environment,
148-
verbose: verbose,
149-
logLevel: logLevel,
150142
);
143+
144+
buildLog.configuration = buildLog.configuration.rebuild((b) {
145+
b.onLog = onLog;
146+
b.verbose = verbose;
147+
});
148+
151149
var options = await BuildOptions.create(
152-
logSubscription,
153150
deleteFilesByDefault: deleteFilesByDefault,
154151
packageGraph: packageGraph,
155152
skipBuildScriptCheck: true,
@@ -172,7 +169,6 @@ Future<TestBuildersResult> testPhases(
172169
buildFilters: buildFilters,
173170
);
174171
await build.beforeExit();
175-
await options.logListener.cancel();
176172

177173
if (checkBuildStatus) {
178174
checkBuild(

build/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## 2.4.3-wip
22

3+
- Improved logging: show what builders are running and, for long-running
4+
builders, where the time is spent.
35
- `AssetNotFoundException` now also reports the missing `path`.
46
- Bump the min sdk to 3.7.0.
57
- Use `build_test` 3.0.0.

build/lib/src/analyzer/resolver.dart

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -169,40 +169,35 @@ class SyntaxErrorInAssetException implements Exception {
169169

170170
@override
171171
String toString() {
172-
final buffer =
173-
StringBuffer()
174-
..writeln('This builder requires Dart inputs without syntax errors.')
175-
..writeln(
176-
'However, ${assetId.uri} (or an existing part) contains the '
177-
'following errors.',
178-
);
172+
final buffer = StringBuffer();
179173

180174
// Avoid generating too much output for syntax errors. The user likely has
181175
// an editor that shows them anyway.
182176
final entries = errorToResult.entries.toList();
177+
var first = true;
183178
for (final errorAndResult in entries.take(_maxErrorsInToString)) {
179+
if (!first) {
180+
buffer.write('\n');
181+
}
182+
first = false;
184183
final error = errorAndResult.key;
185-
// Use a short name: We present the full context by including the asset id
186-
// and this is easier to skim through
187-
final sourceName = error.source.shortName;
188184

189185
final lineInfo = errorAndResult.value.lineInfo;
190186
final position = lineInfo.getLocation(error.offset);
191187

192-
// Output messages like "foo.dart:3:4: Expected a semicolon here."
193-
buffer.writeln(
194-
'$sourceName:${position.lineNumber}:${position.columnNumber}: '
188+
// The file name will be added by `BuildLog`, so write just the line
189+
// number and column, for example: "3:4: Expected a semicolon here."
190+
buffer.write(
191+
'${position.lineNumber}:${position.columnNumber}: '
195192
'${error.message}',
196193
);
197194
}
198195

199196
final additionalErrors = entries.length - _maxErrorsInToString;
200197
if (additionalErrors > 0) {
201-
buffer.writeln('And $additionalErrors more...');
198+
buffer.write('\nAnd $additionalErrors more.');
202199
}
203200

204-
buffer.writeln('\nTry fixing the errors and re-running the build.');
205-
206201
return buffer.toString();
207202
}
208203
}

build/lib/src/builder/logging.dart

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,3 @@ final _default = Logger('build.fallback');
1414
///
1515
/// Will be `null` when not running within a build.
1616
Logger get log => Zone.current[logKey] as Logger? ?? _default;
17-
18-
/// Runs [fn] in an error handling [Zone].
19-
///
20-
/// Any calls to [print] will be logged with `log.warning`, and any errors will
21-
/// be logged with `log.severe`.
22-
///
23-
/// Completes with the first error or result of `fn`, whichever comes first.
24-
Future<T> scopeLogAsync<T>(Future<T> Function() fn, Logger log) {
25-
var done = Completer<T>();
26-
runZonedGuarded(
27-
fn,
28-
(e, st) {
29-
log.severe('', e, st);
30-
if (done.isCompleted) return;
31-
done.completeError(e, st);
32-
},
33-
zoneSpecification: ZoneSpecification(
34-
print: (self, parent, zone, message) {
35-
log.warning(message);
36-
},
37-
),
38-
zoneValues: {logKey: log},
39-
)?.then((result) {
40-
if (done.isCompleted) return;
41-
done.complete(result);
42-
});
43-
return done.future;
44-
}

build/lib/src/generate/run_builder.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44
import 'dart:isolate';
55

6+
import 'package:build_runner_core/build_runner_core.dart';
67
// ignore: implementation_imports
78
import 'package:build_runner_core/src/generate/build_step_impl.dart';
89
// ignore: implementation_imports
@@ -102,7 +103,10 @@ Future<void> runBuilder(
102103
}
103104
}
104105

105-
await scopeLogAsync(() => Future.wait(inputs.map(buildForInput)), logger);
106+
await BuildLogLogger.scopeLogAsync(
107+
() => Future.wait(inputs.map(buildForInput)),
108+
logger,
109+
);
106110

107111
if (shouldDisposeResourceManager) {
108112
await resources.disposeAll();

build/lib/src/generate/run_post_process_builder.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:build_runner_core/build_runner_core.dart';
56
import 'package:logging/logging.dart';
67

78
import '../asset/id.dart';
89
import '../asset/reader.dart';
910
import '../asset/writer.dart';
10-
import '../builder/logging.dart';
1111
import '../builder/post_process_build_step.dart';
12-
import '../builder/post_process_builder.dart';
1312

1413
/// Run [builder] with [inputId] as the primary input.
1514
///
@@ -26,7 +25,7 @@ Future<void> runPostProcessBuilder(
2625
required void Function(AssetId) addAsset,
2726
required void Function(AssetId) deleteAsset,
2827
}) async {
29-
await scopeLogAsync(() async {
28+
await BuildLogLogger.scopeLogAsync(() async {
3029
var buildStep = postProcessBuildStep(
3130
inputId,
3231
reader,

0 commit comments

Comments
 (0)