Skip to content

Commit

Permalink
Add isolate information to logs metadata (flutter#8439)
Browse files Browse the repository at this point in the history
  • Loading branch information
kenzieschmoll authored Oct 15, 2024
1 parent b2919db commit 9552c14
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class LogsTable extends StatelessWidget {
required this.activeSearchMatchNotifier,
});

static final _logRowHeight = scaleByFontFactor(44.0);
static final _logRowHeight = scaleByFontFactor(45.0);

final LoggingController controller;
final List<LogData> data;
Expand Down
26 changes: 14 additions & 12 deletions packages/devtools_app/lib/src/screens/logging/_message_column.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,19 @@ class MessageColumn extends ColumnData<LogData>
data.summary!,
theme.regularTextStyle,
),
if (hasSummary && hasDetails())
WidgetSpan(
child: Icon(
Icons.arrow_right,
size: defaultIconSize,
color: theme.colorScheme.onSurface,
),
),
WidgetSpan(
child: hasSummary && hasDetails()
? Icon(
Icons.arrow_right,
size: defaultIconSize,
color: theme.colorScheme.onSurface,
)
:
// Include an empty SizedBox to ensure a consistent
// height for the text display, regardless of whether
// the log has details information.
SizedBox(height: defaultIconSize),
),
if (hasDetails())
...processAnsiTerminalCodes(
detailsComputed ? data.details! : '<fetching>',
Expand All @@ -95,10 +100,7 @@ class MessageColumn extends ColumnData<LogData>
),
),
Padding(
padding: const EdgeInsets.only(
top: borderPadding,
bottom: densePadding,
),
padding: const EdgeInsets.symmetric(vertical: densePadding),
child: LayoutBuilder(
builder: (context, constraints) {
return MetadataChips(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ class LoggingController extends DisposableController
}

void _handleExtensionEvent(Event e) {
final kind = e.extensionKind!.toLowerCase();
final timestamp = e.timestamp;
final isolateRef = e.isolate;

if (e.extensionKind == FlutterEvent.frame) {
final frame = FrameInfo(e.extensionData!.data);

Expand All @@ -266,10 +270,11 @@ class LoggingController extends DisposableController

log(
LogData(
e.extensionKind!.toLowerCase(),
kind,
jsonEncode(e.extensionData!.data),
e.timestamp,
timestamp,
summary: frameInfoText,
isolateRef: isolateRef,
),
);
} else if (e.extensionKind == FlutterEvent.imageSizesForFrame) {
Expand All @@ -278,10 +283,11 @@ class LoggingController extends DisposableController
for (final image in images) {
log(
LogData(
e.extensionKind!.toLowerCase(),
kind,
jsonEncode(image.json),
e.timestamp,
timestamp,
summary: image.summary,
isolateRef: isolateRef,
),
);
}
Expand All @@ -290,19 +296,21 @@ class LoggingController extends DisposableController

log(
LogData(
e.extensionKind!.toLowerCase(),
kind,
jsonEncode(e.json),
e.timestamp,
timestamp,
summary: navInfo.routeDescription,
isolateRef: isolateRef,
),
);
} else if (_hideSummaryLogKinds.contains(e.extensionKind)) {
log(
LogData(
e.extensionKind!.toLowerCase(),
kind,
jsonEncode(e.json),
e.timestamp,
timestamp,
summary: '',
isolateRef: isolateRef,
),
);
} else if (e.extensionKind == FlutterEvent.serviceExtensionStateChanged) {
Expand All @@ -311,10 +319,11 @@ class LoggingController extends DisposableController

log(
LogData(
e.extensionKind!.toLowerCase(),
kind,
jsonEncode(e.json),
e.timestamp,
timestamp,
summary: '${changedInfo.extension}: ${changedInfo.value}',
isolateRef: isolateRef,
),
);
} else if (e.extensionKind == FlutterEvent.error) {
Expand All @@ -336,21 +345,23 @@ class LoggingController extends DisposableController
final summary = _findFirstSummary(node) ?? node;
log(
LogData(
e.extensionKind!.toLowerCase(),
kind,
jsonEncode(e.extensionData!.data),
e.timestamp,
timestamp,
summary: summary.toDiagnosticsNode().toString(),
level: Level.SEVERE.value,
isError: true,
isolateRef: isolateRef,
),
);
} else {
log(
LogData(
e.extensionKind!.toLowerCase(),
kind,
jsonEncode(e.json),
e.timestamp,
timestamp,
summary: e.json.toString(),
isolateRef: isolateRef,
),
);
}
Expand Down Expand Up @@ -379,13 +390,22 @@ class LoggingController extends DisposableController
};

final message = jsonEncode(event);
log(LogData('gc', message, e.timestamp, summary: summary));
log(
LogData(
'gc',
message,
e.timestamp,
summary: summary,
isolateRef: e.isolateRef,
),
);
}

void _handleDeveloperLogEvent(Event e) {
final eventJson = e.json!;
final service = serviceConnection.serviceManager.service;

final logRecord = _LogRecord(e.json!['logRecord']);
final logRecord = _LogRecord(eventJson['logRecord']);

String? loggerName =
_valueAsString(InstanceRef.parse(logRecord.loggerName));
Expand Down Expand Up @@ -470,6 +490,7 @@ class LoggingController extends DisposableController
isError: isError,
summary: summary,
detailsComputer: detailsComputer,
isolateRef: e.isolateRef,
),
);
}
Expand Down Expand Up @@ -700,6 +721,7 @@ class _StdoutEventHandler {
buffer!.timestamp,
summary: buffer!.summary! + message,
isError: buffer!.isError,
isolateRef: e.isolateRef,
),
);
buffer = null;
Expand All @@ -723,6 +745,7 @@ class _StdoutEventHandler {
e.timestamp,
summary: summary,
isError: isError,
isolateRef: e.isolateRef,
);

if (message == '\n') {
Expand Down Expand Up @@ -773,6 +796,7 @@ class LogData with SearchableDataMixin {
this.isError = false,
this.detailsComputer,
this.node,
this.isolateRef,
}) : level = level ?? (isError ? Level.SEVERE.value : Level.INFO.value) {
final originalDetails = _details;
// Fetch details immediately on creation.
Expand All @@ -796,6 +820,7 @@ class LogData with SearchableDataMixin {
final int? timestamp;
final bool isError;
final String? summary;
final IsolateRef? isolateRef;

String get levelName =>
_levelName ??= LogLevelMetadataChip.generateLogLevel(level).name;
Expand Down Expand Up @@ -933,3 +958,7 @@ class ServiceExtensionStateChangedInfo {
final String? extension;
final Object value;
}

extension on Event {
IsolateRef? get isolateRef => IsolateRef.parse(this.json?['isolate']);
}
109 changes: 74 additions & 35 deletions packages/devtools_app/lib/src/screens/logging/metadata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ class MetadataChips extends StatelessWidget {
foregroundColor: logLevelColors.foreground,
);

// Prepare the isolate chip.
Widget? isolateChip;
final isolateName = data.isolateRef?.name;
if (isolateName != null) {
isolateChip = IsolateChip(
name: isolateName,
id: data.isolateRef?.id,
maxWidth: maxWidth,
backgroundColor: colorScheme.surface,
foregroundColor: colorScheme.onSurface,
outlined: true,
);
}

// Prepare frame time chip.
String? elapsedFrameTimeAsString;
try {
Expand All @@ -72,6 +86,7 @@ class MetadataChips extends StatelessWidget {
foregroundColor: kindColors.foreground,
),
logLevelChip,
if (isolateChip != null) isolateChip,
if (elapsedFrameTimeAsString != null)
FrameElapsedMetaDataChip(
maxWidth: maxWidth,
Expand All @@ -87,26 +102,30 @@ abstract class MetadataChip extends StatelessWidget {
super.key,
required this.maxWidth,
required this.text,
this.tooltip,
this.icon,
this.iconAsset,
this.backgroundColor,
this.foregroundColor,
this.outlined = false,
this.includeLeadingMargin = true,
});

final double maxWidth;
final IconData? icon;
final String? iconAsset;
final String text;
final String? tooltip;
final Color? backgroundColor;
final Color? foregroundColor;
final bool outlined;
final bool includeLeadingMargin;

static const horizontalPadding = densePadding;
static const verticalPadding = borderPadding;
static const iconPadding = densePadding;
static final height = scaleByFontFactor(18.0);
static const _borderRadius = 4.0;
static final _metadataIconSize = scaleByFontFactor(12.0);

@override
Widget build(BuildContext context) {
Expand All @@ -116,41 +135,49 @@ abstract class MetadataChip extends StatelessWidget {
final foregroundColor =
this.foregroundColor ?? theme.colorScheme.onSecondaryContainer;

return Container(
constraints: BoxConstraints(maxWidth: maxWidth),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(_borderRadius),
),
margin: includeLeadingMargin
? const EdgeInsets.only(left: denseSpacing)
: null,
padding: const EdgeInsets.symmetric(
horizontal: horizontalPadding,
vertical: verticalPadding,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null || iconAsset != null) ...[
DevToolsIcon(
icon: icon,
iconAsset: iconAsset,
size: defaultIconSize,
color: foregroundColor,
),
const SizedBox(width: iconPadding),
] else
// Include an empty SizedBox to ensure a consistent height for the
// chips, regardless of whether the chip includes an icon.
SizedBox(height: defaultIconSize),
RichText(
text: TextSpan(
text: text,
style: theme.regularTextStyleWithColor(foregroundColor),
return maybeWrapWithTooltip(
tooltip: tooltip,
child: Container(
constraints: BoxConstraints(maxWidth: maxWidth),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(_borderRadius),
border: outlined
? Border.all(color: theme.colorScheme.subtleTextColor)
: null,
),
margin: includeLeadingMargin
? const EdgeInsets.only(left: denseSpacing)
: null,
padding: const EdgeInsets.symmetric(
horizontal: horizontalPadding,
vertical: verticalPadding,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null || iconAsset != null) ...[
DevToolsIcon(
icon: icon,
iconAsset: iconAsset,
size: _metadataIconSize,
color: foregroundColor,
),
const SizedBox(width: iconPadding),
] else
// Include an empty SizedBox to ensure a consistent height for the
// chips, regardless of whether the chip includes an icon.
SizedBox(height: _metadataIconSize),
RichText(
text: TextSpan(
text: text,
style: theme
.regularTextStyleWithColor(foregroundColor)
.copyWith(fontSize: smallFontSize),
),
),
),
],
],
),
),
);
}
Expand Down Expand Up @@ -254,3 +281,15 @@ class LogLevelMetadataChip extends MetadataChip {
return (background: background, foreground: foreground);
}
}

class IsolateChip extends MetadataChip {
const IsolateChip({
super.key,
required String name,
required String? id,
required super.maxWidth,
super.backgroundColor,
super.foregroundColor,
super.outlined = false,
}) : super(text: 'isolate: $name', tooltip: id);
}
Loading

0 comments on commit 9552c14

Please sign in to comment.