[analysis_server] Exclude instrumentation log file from logged watch events to prevent loops

Fixes https://github.com/dart-lang/sdk/issues/48885.

Change-Id: Idebfd9d4f2867b3053c0ece49b300926956fab2a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/275061
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Danny Tuppeny 2022-12-12 20:09:36 +00:00 committed by Commit Queue
parent e113df3da5
commit ef2c7916f5
3 changed files with 54 additions and 3 deletions

View file

@ -274,8 +274,9 @@ class Driver implements ServerStarter {
: [this.instrumentationService!];
if (logFilePath != null) {
_rollLogFiles(logFilePath, 5);
allInstrumentationServices.add(
InstrumentationLogAdapter(FileInstrumentationLogger(logFilePath)));
allInstrumentationServices.add(InstrumentationLogAdapter(
FileInstrumentationLogger(logFilePath),
watchEventExclusionFiles: {logFilePath}));
}
var errorNotifier = ErrorNotifier();

View file

@ -27,9 +27,19 @@ class InstrumentationLogAdapter implements InstrumentationService {
/// A logger used to log instrumentation in string format.
final InstrumentationLogger _instrumentationLogger;
/// Files that should not have their watch events logged (to prevent feedback
/// loops).
final Set<String>? _watchEventExclusionFiles;
/// Initialize a newly created instrumentation service to communicate with the
/// given [_instrumentationLogger].
InstrumentationLogAdapter(this._instrumentationLogger);
///
/// Any file paths in [watchEventExclusionFiles] will be excluded from the
/// logging of watch events (to prevent feedback loops).
InstrumentationLogAdapter(
this._instrumentationLogger, {
Set<String>? watchEventExclusionFiles,
}) : _watchEventExclusionFiles = watchEventExclusionFiles;
/// The current time, expressed as a decimal encoded number of milliseconds.
String get _timestamp => DateTime.now().millisecondsSinceEpoch.toString();
@ -142,6 +152,10 @@ class InstrumentationLogAdapter implements InstrumentationService {
@override
void logWatchEvent(String folderPath, String filePath, String changeType) {
if (_watchEventExclusionFiles?.contains(filePath) ?? false) {
return;
}
_instrumentationLogger
.log(_join([TAG_WATCH_EVENT, folderPath, filePath, changeType]));
}

View file

@ -13,6 +13,11 @@ main() {
@reflectiveTest
class InstrumentationServiceTest {
void assertNoLogs(TestInstrumentationLogger logger) {
String sent = logger.logged.toString();
expect(sent, isEmpty);
}
void assertNormal(
TestInstrumentationLogger logger, String tag, String message) {
String sent = logger.logged.toString();
@ -171,6 +176,37 @@ class InstrumentationServiceTest {
endsWith(
':myUuid:someClientId:someClientVersion:aServerVersion:anSdkVersion\n'));
}
void test_logWatch() {
TestInstrumentationLogger logger = TestInstrumentationLogger();
InstrumentationService service = InstrumentationLogAdapter(logger);
service.logWatchEvent('/folder', '/folder/file.txt', 'modify');
assertNormal(
logger,
InstrumentationLogAdapter.TAG_WATCH_EVENT,
'/folder:/folder/file.txt:modify',
);
}
void test_logWatch_exclusions_excluded() {
TestInstrumentationLogger logger = TestInstrumentationLogger();
InstrumentationService service = InstrumentationLogAdapter(logger,
watchEventExclusionFiles: {'/folder/excluded.txt'});
service.logWatchEvent('/folder', '/folder/excluded.txt', 'modify');
assertNoLogs(logger);
}
void test_logWatch_exclusions_notExcluded() {
TestInstrumentationLogger logger = TestInstrumentationLogger();
InstrumentationService service = InstrumentationLogAdapter(logger,
watchEventExclusionFiles: {'/folder/excluded.txt'});
service.logWatchEvent('/folder', '/folder/file.txt', 'modify');
assertNormal(
logger,
InstrumentationLogAdapter.TAG_WATCH_EVENT,
'/folder:/folder/file.txt:modify',
);
}
}
@reflectiveTest