[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>
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 767ee6f..343ab32 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -274,8 +274,9 @@
: [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 cd1393c..19b73d4 100644
--- a/pkg/analyzer/lib/instrumentation/log_adapter.dart
+++ b/pkg/analyzer/lib/instrumentation/log_adapter.dart
@@ -27,9 +27,19 @@
/// 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 @@
@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 8ed202b..077ab94 100644
--- a/pkg/analyzer/test/instrumentation/instrumentation_test.dart
+++ b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
@@ -13,6 +13,11 @@
@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 @@
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