diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart index 767ee6ffc14..343ab325e9a 100644 --- a/pkg/analysis_server/lib/src/server/driver.dart +++ b/pkg/analysis_server/lib/src/server/driver.dart @@ -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(); diff --git a/pkg/analyzer/lib/instrumentation/log_adapter.dart b/pkg/analyzer/lib/instrumentation/log_adapter.dart index cd1393ca4aa..19b73d47bc0 100644 --- a/pkg/analyzer/lib/instrumentation/log_adapter.dart +++ b/pkg/analyzer/lib/instrumentation/log_adapter.dart @@ -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? _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? 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])); } diff --git a/pkg/analyzer/test/instrumentation/instrumentation_test.dart b/pkg/analyzer/test/instrumentation/instrumentation_test.dart index 8ed202bc020..077ab945235 100644 --- a/pkg/analyzer/test/instrumentation/instrumentation_test.dart +++ b/pkg/analyzer/test/instrumentation/instrumentation_test.dart @@ -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