-
Notifications
You must be signed in to change notification settings - Fork 399
implemented har feature #7970
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
implemented har feature #7970
Changes from 7 commits
da7252d
f6f9491
a1ba9bd
ef3a637
058e053
ae292ad
9d5231b
1b9e483
0e5cdbb
5c306c1
5d8fc75
16faad7
f843862
1c4442c
8c08441
625b452
3dd0274
0261ab7
b77c454
484e9f2
f504b18
258e34e
f741882
eb7f848
a608451
b734dc3
449f9e6
0175330
6c13f54
f332b40
70d9468
6f03ce2
6c73e28
fb4fd58
0a0b4be
21f6a5f
2d12a0d
df0b56f
23295fc
1398c0e
7bbdf80
e1c9791
c0cb621
daccfde
2692ea1
01f5122
c5c1842
2734fcb
fb10b26
8a65da8
6443964
89dae77
b26b833
6d4177b
83b4a3f
7d211fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| import '../../../devtools_app.dart'; | ||
| import '../../shared/analytics/constants.dart'; | ||
|
|
||
| /// Builds a HAR (HTTP Archive) object from a list of HTTP requests. | ||
| /// | ||
| /// The HAR format is a JSON-based format used for logging a web browser's | ||
| /// interaction with a site. It is useful for web performance analysis and | ||
| /// debugging. This function constructs the HAR object based on the 1.2 | ||
| /// specification. | ||
| /// | ||
| /// For more details on the HAR format, see the [HAR 1.2 Specification](https://github.com/ahmadnassri/har-spec/blob/master/versions/1.2.md). | ||
|
bkonyi marked this conversation as resolved.
|
||
| /// | ||
| /// Parameters: | ||
| /// - [httpRequests]: A list of DartIOHttpRequestData data. | ||
| /// | ||
| /// Returns: | ||
| /// - A Map representing the HAR object. | ||
| Map<String, dynamic> buildHar(List<DartIOHttpRequestData> httpRequests) { | ||
|
hrajwade96 marked this conversation as resolved.
Outdated
|
||
| // Build the creator | ||
| final creator = { | ||
|
hrajwade96 marked this conversation as resolved.
Outdated
|
||
| NetworkEventKeys.name: NetworkEventDefaults.creatorName, | ||
| NetworkEventKeys.creatorVersion: NetworkEventDefaults.creatorVersion, | ||
| }; | ||
|
|
||
| // Build the pages | ||
| final pages = [ | ||
| { | ||
| NetworkEventKeys.startedDateTime: | ||
| httpRequests.first.startTimestamp.toUtc().toIso8601String(), | ||
| NetworkEventKeys.id: NetworkEventDefaults.id, | ||
| NetworkEventKeys.title: NetworkEventDefaults.title, | ||
| NetworkEventKeys.pageTimings: { | ||
| NetworkEventKeys.onContentLoad: NetworkEventDefaults.onContentLoad, | ||
| NetworkEventKeys.onLoad: NetworkEventDefaults.onLoad, | ||
| }, | ||
| }, | ||
| ]; | ||
|
|
||
| // Build the entries | ||
| final entries = httpRequests.map((e) { | ||
| final requestCookies = e.requestCookies.map((cookie) { | ||
| return { | ||
| NetworkEventKeys.name: cookie.name, | ||
| NetworkEventKeys.value: cookie.value, | ||
| 'path': cookie.path, | ||
| 'domain': cookie.domain, | ||
| 'expires': cookie.expires?.toUtc().toIso8601String(), | ||
| 'httpOnly': cookie.httpOnly, | ||
| 'secure': cookie.secure, | ||
| }; | ||
| }).toList(); | ||
|
|
||
| final requestHeaders = e.requestHeaders?.entries.map((header) { | ||
| var value = header.value; | ||
| if (value is List) { | ||
| value = value.first; | ||
| } | ||
| return { | ||
| NetworkEventKeys.name: header.key, | ||
| NetworkEventKeys.value: value, | ||
| }; | ||
| }).toList(); | ||
|
|
||
| final queryString = Uri.parse(e.uri).queryParameters.entries.map((param) { | ||
| return { | ||
| NetworkEventKeys.name: param.key, | ||
| NetworkEventKeys.value: param.value, | ||
| }; | ||
| }).toList(); | ||
|
|
||
| final responseCookies = e.responseCookies.map((cookie) { | ||
| return { | ||
| NetworkEventKeys.name: cookie.name, | ||
| NetworkEventKeys.value: cookie.value, | ||
| 'path': cookie.path, | ||
| 'domain': cookie.domain, | ||
| 'expires': cookie.expires?.toUtc().toIso8601String(), | ||
| 'httpOnly': cookie.httpOnly, | ||
| 'secure': cookie.secure, | ||
| }; | ||
| }).toList(); | ||
|
|
||
| final responseHeaders = e.responseHeaders?.entries.map((header) { | ||
| var value = header.value; | ||
| if (value is List) { | ||
| value = value.first; | ||
| } | ||
| return { | ||
| NetworkEventKeys.name: header.key, | ||
| NetworkEventKeys.value: value, | ||
| }; | ||
| }).toList(); | ||
|
|
||
| return { | ||
| NetworkEventKeys.pageref: NetworkEventDefaults.id, | ||
| NetworkEventKeys.startedDateTime: | ||
| e.startTimestamp.toUtc().toIso8601String(), | ||
| NetworkEventKeys.time: e.duration?.inMilliseconds, | ||
| NetworkEventKeys.request: { | ||
| NetworkEventKeys.method: e.method.toUpperCase(), | ||
| NetworkEventKeys.url: e.uri.toString(), | ||
| NetworkEventKeys.httpVersion: NetworkEventDefaults.httpVersion, | ||
| NetworkEventKeys.cookies: requestCookies, | ||
| NetworkEventKeys.headers: requestHeaders, | ||
| NetworkEventKeys.queryString: queryString, | ||
| NetworkEventKeys.postData: { | ||
| NetworkEventKeys.mimeType: e.contentType, | ||
| NetworkEventKeys.text: e.requestBody, | ||
| }, | ||
| NetworkEventKeys.headersSize: NetworkEventDefaults.headersSize, | ||
| NetworkEventKeys.bodySize: NetworkEventDefaults.bodySize, | ||
| }, | ||
| NetworkEventKeys.response: { | ||
| NetworkEventKeys.status: e.status, | ||
| NetworkEventKeys.statusText: '', | ||
| NetworkEventKeys.httpVersion: NetworkEventDefaults.responseHttpVersion, | ||
| NetworkEventKeys.cookies: responseCookies, | ||
| NetworkEventKeys.headers: responseHeaders, | ||
| NetworkEventKeys.content: { | ||
| NetworkEventKeys.size: e.responseBody?.length, | ||
| NetworkEventKeys.mimeType: e.type, | ||
| NetworkEventKeys.text: e.responseBody, | ||
| }, | ||
| NetworkEventKeys.redirectURL: '', | ||
| NetworkEventKeys.headersSize: NetworkEventDefaults.headersSize, | ||
| NetworkEventKeys.bodySize: NetworkEventDefaults.bodySize, | ||
| }, | ||
| NetworkEventKeys.cache: {}, | ||
| NetworkEventKeys.timings: { | ||
| NetworkEventKeys.blocked: NetworkEventDefaults.blocked, | ||
| NetworkEventKeys.dns: NetworkEventDefaults.dns, | ||
| NetworkEventKeys.connect: NetworkEventDefaults.connect, | ||
| NetworkEventKeys.send: NetworkEventDefaults.send, | ||
| NetworkEventKeys.wait: e.duration!.inMilliseconds - 2, | ||
| NetworkEventKeys.receive: NetworkEventDefaults.receive, | ||
| NetworkEventKeys.ssl: NetworkEventDefaults.ssl, | ||
| }, | ||
| NetworkEventKeys.serverIPAddress: NetworkEventDefaults.serverIPAddress, | ||
| NetworkEventKeys.connection: e.hashCode.toString(), | ||
| NetworkEventKeys.comment: '', | ||
| }; | ||
| }).toList(); | ||
|
|
||
| // Assemble the final HAR object | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ubernit: indent
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry didn't get you |
||
| return { | ||
| NetworkEventKeys.log: { | ||
| NetworkEventKeys.version: NetworkEventDefaults.logVersion, | ||
| NetworkEventKeys.creator: creator, | ||
| NetworkEventKeys.pages: pages, | ||
| NetworkEventKeys.entries: entries, | ||
| }, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| // Copyright 2024 The Chromium Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| part of '../constants.dart'; | ||
|
bkonyi marked this conversation as resolved.
|
||
|
|
||
| class NetworkEvent { | ||
|
kenzieschmoll marked this conversation as resolved.
Outdated
|
||
| static const networkDownloadHar = 'networkDownloadHar'; | ||
|
kenzieschmoll marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| class NetworkEventKeys { | ||
|
kenzieschmoll marked this conversation as resolved.
Outdated
|
||
| static const log = 'log'; | ||
| static const version = 'version'; | ||
| static const creator = 'creator'; | ||
| static const name = 'name'; | ||
| static const creatorVersion = 'version'; | ||
| static const pages = 'pages'; | ||
| static const startedDateTime = 'startedDateTime'; | ||
| static const id = 'id'; | ||
| static const title = 'title'; | ||
| static const pageTimings = 'pageTimings'; | ||
| static const onContentLoad = 'onContentLoad'; | ||
| static const onLoad = 'onLoad'; | ||
| static const entries = 'entries'; | ||
| static const pageref = 'pageref'; | ||
| static const time = 'time'; | ||
| static const request = 'request'; | ||
| static const method = 'method'; | ||
| static const url = 'url'; | ||
| static const httpVersion = 'httpVersion'; | ||
| static const cookies = 'cookies'; | ||
| static const headers = 'headers'; | ||
| static const queryString = 'queryString'; | ||
| static const postData = 'postData'; | ||
| static const mimeType = 'mimeType'; | ||
| static const text = 'text'; | ||
| static const headersSize = 'headersSize'; | ||
| static const bodySize = 'bodySize'; | ||
| static const response = 'response'; | ||
| static const status = 'status'; | ||
| static const statusText = 'statusText'; | ||
| static const content = 'content'; | ||
| static const size = 'size'; | ||
| static const redirectURL = 'redirectURL'; | ||
| static const cache = 'cache'; | ||
| static const timings = 'timings'; | ||
| static const blocked = 'blocked'; | ||
| static const dns = 'dns'; | ||
| static const connect = 'connect'; | ||
| static const send = 'send'; | ||
| static const wait = 'wait'; | ||
| static const receive = 'receive'; | ||
| static const ssl = 'ssl'; | ||
| static const serverIPAddress = 'serverIPAddress'; | ||
| static const connection = 'connection'; | ||
| static const comment = 'comment'; | ||
| static const value = 'value'; | ||
| } | ||
|
|
||
| class NetworkEventDefaults { | ||
| static const logVersion = '1.2'; | ||
| static const creatorName = 'devtools'; | ||
| static const creatorVersion = '0.0.2'; | ||
|
hrajwade96 marked this conversation as resolved.
Outdated
|
||
| static const id = 'page_0'; | ||
| static const title = 'FlutterCapture'; | ||
|
hrajwade96 marked this conversation as resolved.
Outdated
|
||
| static const onContentLoad = -1; | ||
| static const onLoad = -1; | ||
| static const httpVersion = 'HTTP/1.1'; | ||
| static const responseHttpVersion = 'http/2.0'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be hardcoded?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this field doesn't seem to be available in the 'DartIOHttpRequestData'
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we put some placeholder like "Unknown" instead? Maybe @brianquinlan knows if this information is available somewhere. |
||
| static const headersSize = -1; | ||
| static const bodySize = -1; | ||
| static const blocked = -1; | ||
| static const dns = -1; | ||
| static const connect = -1; | ||
| static const send = 1; | ||
| static const receive = 1; | ||
| static const ssl = -1; | ||
| static const serverIPAddress = '10.0.0.1'; | ||
|
hrajwade96 marked this conversation as resolved.
Outdated
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -113,7 +113,8 @@ enum ExportFileType { | |
| json, | ||
| csv, | ||
| yaml, | ||
| data; | ||
| data, | ||
| har; | ||
|
|
||
| @override | ||
| String toString() => name; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.