Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add selection analytics for NetworkScreen #3360

Merged
merged 6 commits into from
Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/devtools_app/lib/src/analytics/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import '../inspector/inspector_screen.dart';
import '../logging/logging_screen.dart';
import '../memory/memory_screen.dart';
import '../network/network_screen.dart';
import '../performance/performance_screen.dart';
import '../profiler/profiler_screen.dart';

Expand All @@ -22,6 +23,7 @@ const String inspector = InspectorScreen.id;
const String performance = PerformanceScreen.id;
const String cpuProfiler = ProfilerScreen.id;
const String memory = MemoryScreen.id;
const String network = NetworkScreen.id;
const String logging = LoggingScreen.id;

// GA events not associated with a any screen e.g., hotReload, hotRestart, etc
Expand Down
31 changes: 25 additions & 6 deletions packages/devtools_app/lib/src/http/http_request_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:mime/mime.dart';
import 'package:vm_service/vm_service.dart';

Expand Down Expand Up @@ -169,10 +169,6 @@ abstract class HttpRequestData extends NetworkRequest {
return false;
}

/// True if the HTTP request hasn't completed yet, determined by the lack of
/// an end event.
bool get inProgress;

/// All instant events logged to the timeline for this HTTP request.
List<HttpInstantEvent> get instantEvents;

Expand Down Expand Up @@ -481,18 +477,23 @@ class TimelineHttpRequestData extends HttpRequestData {
String toString() => '$method $uri';
}

int _dartIoHttpRequestWrapperId = 0;

class DartIOHttpRequestData extends HttpRequestData {
DartIOHttpRequestData(
int timelineMicrosBase,
this._request,
) : super(timelineMicrosBase) {
) : wrapperId = _dartIoHttpRequestWrapperId++,
super(timelineMicrosBase) {
if (_request.isResponseComplete) {
getFullRequestData();
}
}

HttpProfileRequestRef _request;

final int wrapperId;

Future<void> getFullRequestData() {
return serviceManager.service
.getHttpProfileRequest(
Expand Down Expand Up @@ -674,4 +675,22 @@ class DartIOHttpRequestData extends HttpRequestData {
lastTime = instantTime;
}
}

@override
bool operator ==(other) {
return other is DartIOHttpRequestData &&
wrapperId == other.wrapperId &&
super == other;
}

@override
int get hashCode => hashValues(
wrapperId,
method,
uri,
contentType,
type,
port,
startTimestamp,
);
}
35 changes: 35 additions & 0 deletions packages/devtools_app/lib/src/network/network_model.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:flutter/material.dart';
import 'package:vm_service/vm_service.dart';

import '../http/http_request_data.dart';
Expand Down Expand Up @@ -29,6 +30,9 @@ abstract class NetworkRequest with DataSearchStateMixin {

bool get didFail;

/// True if the request hasn't completed yet.
bool get inProgress;

String get durationDisplay =>
'Duration: ${duration != null ? msText(duration) : 'Pending'}';

Expand All @@ -38,6 +42,34 @@ abstract class NetworkRequest with DataSearchStateMixin {

@override
String toString() => '$method $uri';

@override
bool operator ==(other) {
return other is NetworkRequest &&
runtimeType == other.runtimeType &&
startTimestamp == other.startTimestamp &&
method == other.method &&
uri == other.uri &&
contentType == other.contentType &&
type == other.type &&
port == other.port &&
(inProgress == other.inProgress
? (endTimestamp == other.endTimestamp &&
duration == other.duration &&
status == other.status &&
didFail == other.didFail)
: true);
}

@override
int get hashCode => hashValues(
method,
uri,
contentType,
type,
port,
startTimestamp,
);
}

class WebSocket extends NetworkRequest {
Expand Down Expand Up @@ -107,6 +139,9 @@ class WebSocket extends NetworkRequest {
@override
String get status => '101';

@override
bool get inProgress => false;

@override
bool operator ==(other) => other is WebSocket && id == other.id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import 'package:flutter/material.dart';

import '../analytics/constants.dart' as analytics_constants;
import '../common_widgets.dart';
import '../http/http_request_data.dart';
import '../theme.dart';
import '../ui/tab.dart';
import 'network_model.dart';
import 'network_request_inspector_views.dart';
Expand Down Expand Up @@ -39,6 +39,7 @@ class NetworkRequestInspector extends StatelessWidget {
Widget _buildTab(String tabName) {
return DevToolsTab(
key: ValueKey<String>(tabName),
gaId: 'requestInspectorTab_$tabName',
child: Text(
tabName,
overflow: TextOverflow.ellipsis,
Expand All @@ -48,51 +49,29 @@ class NetworkRequestInspector extends StatelessWidget {

@override
Widget build(BuildContext context) {
final tabs = <Tab>[
_buildTab(_overviewTabTitle),
final tabs = <DevToolsTab>[
_buildTab(NetworkRequestInspector._overviewTabTitle),
if (data is HttpRequestData) ...[
_buildTab(_headersTabTitle),
_buildTab(NetworkRequestInspector._headersTabTitle),
if ((data as HttpRequestData).requestBody != null)
_buildTab(_requestTabTitle),
_buildTab(NetworkRequestInspector._requestTabTitle),
if ((data as HttpRequestData).responseBody != null)
_buildTab(_responseTabTitle),
if ((data as HttpRequestData).hasCookies) _buildTab(_cookiesTabTitle),
_buildTab(NetworkRequestInspector._responseTabTitle),
if ((data as HttpRequestData).hasCookies)
_buildTab(NetworkRequestInspector._cookiesTabTitle),
],
];
final tabViews = [
NetworkRequestOverviewView(data),
if (data is HttpRequestData) ...[
HttpRequestHeadersView(data),
if ((data as HttpRequestData).requestBody != null)
HttpRequestView(data),
if ((data as HttpRequestData).responseBody != null)
HttpResponseView(data),
if ((data as HttpRequestData).hasCookies) HttpRequestCookiesView(data),
],
];
final tabbedContent = DefaultTabController(
length: tabs.length,
child: Column(
children: [
Row(
children: [
Flexible(
child: TabBar(
labelColor: Theme.of(context).textTheme.bodyText1.color,
tabs: tabs,
),
),
],
),
Expanded(
child: TabBarView(
physics: defaultTabBarViewPhysics,
children: [
NetworkRequestOverviewView(data),
if (data is HttpRequestData) ...[
HttpRequestHeadersView(data),
if ((data as HttpRequestData).requestBody != null)
HttpRequestView(data),
if ((data as HttpRequestData).responseBody != null)
HttpResponseView(data),
if ((data as HttpRequestData).hasCookies)
HttpRequestCookiesView(data),
],
],
),
),
],
),
);

return Card(
margin: EdgeInsets.zero,
Expand All @@ -102,11 +81,15 @@ class NetworkRequestInspector extends StatelessWidget {
? Center(
child: Text(
'No request selected',
key: noRequestSelectedKey,
key: NetworkRequestInspector.noRequestSelectedKey,
style: Theme.of(context).textTheme.headline6,
),
)
: tabbedContent,
: AnalyticsTabbedView(
tabs: tabs,
tabViews: tabViews,
gaScreen: analytics_constants.network,
),
),
);
}
Expand Down
Loading