Skip to content

Commit

Permalink
Improve IPL of the logging page by two orders of magnitude (#8500)
Browse files Browse the repository at this point in the history
  • Loading branch information
kenzieschmoll authored Nov 4, 2024
1 parent 86abd56 commit 33e67d5
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 54 deletions.
122 changes: 68 additions & 54 deletions packages/devtools_app/lib/src/screens/logging/logging_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -541,8 +541,26 @@ class LoggingController extends DisposableController

void log(LogData log) {
data.add(log);
_updateForRetentionLimit(updateData: false);
_updateData(data);
if (includeLogForFilter(log, filter: activeFilter.value)) {
// This will notify since [filteredData] is a [ListValueNotifier].
filteredData.add(log);
}
// TODO(kenz): we don't need to re-filter the data from this method if we
// trim the logs for the retention limit. This would require some
// refactoring to the _updateData method to support updating the notifiers
// without re-filtering all the data.
// If we need to trim logs to meet the retention limit, this will call
// [_updateData] and perform a re-filter of all the logs.
_updateForRetentionLimit();

// TODO(kenz): this will traverse all the logs to refresh search matches.
// We don't need to do this. We could optimize further by updating the
// search match status for the individual log and for the controller without
// traversing the entire data set. This is a no-op when the search value is
// empty, but this cost is O(N*N) when a search value is present.
refreshSearchMatches();

_updateStatus();
}

void _updateForRetentionLimit({
Expand Down Expand Up @@ -676,65 +694,61 @@ class LoggingController extends DisposableController
@override
Iterable<LogData> get currentDataToSearchThrough => filteredData.value;

@override
void filterData(Filter<LogData> filter) {
super.filterData(filter);

bool filterCallback(LogData log) {
final filteredOutBySettingFilters = filter.settingFilters.any(
(settingFilter) => !settingFilter.includeData(log),
);
if (filteredOutBySettingFilters) return false;

final queryFilter = filter.queryFilter;
if (!queryFilter.isEmpty) {
final filteredOutByQueryFilterArgument = queryFilter
.filterArguments.values
.any((argument) => !argument.matchesValue(log));
if (filteredOutByQueryFilterArgument) return false;

if (filter.queryFilter.substringExpressions.isNotEmpty) {
for (final substring in filter.queryFilter.substringExpressions) {
final matchesKind = log.kind.caseInsensitiveContains(substring);
if (matchesKind) return true;

final matchesLevel =
log.levelName.caseInsensitiveContains(substring);
if (matchesLevel) return true;

final matchesIsolateName =
log.isolateRef?.name?.caseInsensitiveContains(substring) ??
false;
if (matchesIsolateName) return true;

final zone = log.zone;
final matchesZoneName =
zone?.name?.caseInsensitiveContains(substring) ?? false;
final matchesZoneIdentity = zone?.identityHashCode
?.toString()
.caseInsensitiveContains(substring) ??
false;
if (matchesZoneName || matchesZoneIdentity) return true;

final matchesSummary = log.summary != null &&
log.summary!.caseInsensitiveContains(substring);
if (matchesSummary) return true;

final matchesDetails = log.details != null &&
log.details!.caseInsensitiveContains(substring);
if (matchesDetails) return true;
}
return false;
bool includeLogForFilter(LogData log, {required Filter filter}) {
final filteredOutBySettingFilters = filter.settingFilters.any(
(settingFilter) => !settingFilter.includeData(log),
);
if (filteredOutBySettingFilters) return false;

final queryFilter = filter.queryFilter;
if (!queryFilter.isEmpty) {
final filteredOutByQueryFilterArgument = queryFilter
.filterArguments.values
.any((argument) => !argument.matchesValue(log));
if (filteredOutByQueryFilterArgument) return false;

if (filter.queryFilter.substringExpressions.isNotEmpty) {
for (final substring in filter.queryFilter.substringExpressions) {
final matchesKind = log.kind.caseInsensitiveContains(substring);
if (matchesKind) return true;

final matchesLevel = log.levelName.caseInsensitiveContains(substring);
if (matchesLevel) return true;

final matchesIsolateName =
log.isolateRef?.name?.caseInsensitiveContains(substring) ?? false;
if (matchesIsolateName) return true;

final zone = log.zone;
final matchesZoneName =
zone?.name?.caseInsensitiveContains(substring) ?? false;
final matchesZoneIdentity = zone?.identityHashCode
?.toString()
.caseInsensitiveContains(substring) ??
false;
if (matchesZoneName || matchesZoneIdentity) return true;

final matchesSummary = log.summary != null &&
log.summary!.caseInsensitiveContains(substring);
if (matchesSummary) return true;

final matchesDetails = log.details != null &&
log.details!.caseInsensitiveContains(substring);
if (matchesDetails) return true;
}
return false;
}

return true;
}
return true;
}

@override
void filterData(Filter<LogData> filter) {
super.filterData(filter);
filteredData
..clear()
..addAll(
data.where(filterCallback).toList(),
data.where((log) => includeLogForFilter(log, filter: filter)).toList(),
);
}
}
Expand Down
36 changes: 36 additions & 0 deletions packages/devtools_app/macos/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
/* End PBXAggregateTarget section */

/* Begin PBXBuildFile section */
11595299B00138FF6A219878 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46084CB9F244837191E61B73 /* Pods_RunnerTests.framework */; };
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
Expand Down Expand Up @@ -62,6 +63,7 @@

/* Begin PBXFileReference section */
11BB555C0F1767B9B5CB7CE0 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
13053082F27293B7166BCBED /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
Expand All @@ -78,18 +80,22 @@
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
46084CB9F244837191E61B73 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5062035DDDD18FB35E98D5B6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
68C587FFA5A0B8F46A0C5150 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
A7CE48BF63861DD9F3A9FA2F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
BDEB23F5F07C7F498EB77EA2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
E11974409F5281249C10F0E1 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
331C80D2294CF70F00263BE5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
11595299B00138FF6A219878 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -185,6 +191,9 @@
11BB555C0F1767B9B5CB7CE0 /* Pods-Runner.debug.xcconfig */,
68C587FFA5A0B8F46A0C5150 /* Pods-Runner.release.xcconfig */,
A7CE48BF63861DD9F3A9FA2F /* Pods-Runner.profile.xcconfig */,
E11974409F5281249C10F0E1 /* Pods-RunnerTests.debug.xcconfig */,
BDEB23F5F07C7F498EB77EA2 /* Pods-RunnerTests.release.xcconfig */,
13053082F27293B7166BCBED /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
Expand All @@ -194,6 +203,7 @@
isa = PBXGroup;
children = (
5062035DDDD18FB35E98D5B6 /* Pods_Runner.framework */,
46084CB9F244837191E61B73 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
Expand All @@ -205,6 +215,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
3E485AF46E5EF6A810E8A04C /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
Expand Down Expand Up @@ -349,6 +360,28 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
3E485AF46E5EF6A810E8A04C /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
DC1C8B6797A659BE5B59B986 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -439,6 +472,7 @@
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E11974409F5281249C10F0E1 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
Expand All @@ -453,6 +487,7 @@
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = BDEB23F5F07C7F498EB77EA2 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
Expand All @@ -467,6 +502,7 @@
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 13053082F27293B7166BCBED /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
Expand Down
2 changes: 2 additions & 0 deletions packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ TODO: Remove this section if there are not any general updates.
* Fetch log details immediately upon receiving logs so that log data is not lost
due to lazy loading. - [#8421](https://github.com/flutter/devtools/pull/8421)

* Reduce initial page load time. - [#8500](https://github.com/flutter/devtools/pull/8500)

* Added support for displaying metadata, such as log
severity, category, zone, and isolate -
[#8419](https://github.com/flutter/devtools/pull/8419),
Expand Down

0 comments on commit 33e67d5

Please sign in to comment.