Chromium 网络栈之NetLog
发布于 2021-11-24
NetLog 是 Chromium 网络栈记录事件的机制,可用于辅助定位网络问题或者分析性能。
chrome://net-export/ 记录 NetLog
Chromium 浏览器提供一个可视化的界面来录制浏览器的NetLog。打开 chrome://net-export/
,如下图所示:
我们点击 Start Logging to Disk 按钮,就开始录制 NetLog。然后我们打开一些网页,对浏览器做一些操作,再点击 Stop Logging 按钮,就可以把 NetLog 的数据保存到磁盘文件 chrome-net-export-log.json
中了,如下图所示:
chrome://net-export/
的功能实际上是代码中 NetLogExporter 类实现的。
NetLog 数据
可以看到 NetLog 保存的数据文件 chrome-net-export-log.json
是 json 的格式。
它主要有 3 部分:
- constants,可选的,用于解码 log 里面一些常量值。
- events,记录事件数据。
- polledData,可选的,记录附加的网络栈信息。
NetLog 中的 events 数据,其实对应就是代码中的 NetLogEntryData 中保存的数据。
字段 | 类型 | 说明 |
---|---|---|
time | string | 事件发生的毫秒值 |
type | number | 事件的类型id |
source | object | 事件源信息 |
phase | number | 事件的阶段 BEGIN, END, NONE |
params | object | 可选的字段,事件相关的数据 |
字段 source 的值是个对象,它的内部字段如下:
- id,该事件数据源的唯一ID
- type,事件源的类型
- start_time,事件源的开始时间
查看 NetLog 数据
在之前 Chromium 版本里,浏览器打开 chrome://net-internals/
,可以加载查看 NetLog 数据。较新版本的 Chromium 已经移除了 chrome://net-internals/
,但是我们可以在网页 https://netlog-viewer.appspot.com/
中查看。
加载一个已经录制好的 NetLog 数据文件,效果如下:
可以看到 NetLog 记录的数据是非常全面的。对应我们分析网络实际的工作情况非常有帮助。这个工具的使用并不复杂,就不赘述了。
FileNetLogObserver
我们实现一个 NetLogController 类 通过调用 FileNetLogObserver 的接口把 NetLog 中的数据写到文件中:
net_log_controller.h 文件内容:
#ifndef NET_LOG_CONTROLLER_H_
#define NET_LOG_CONTROLLER_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "net/log/file_net_log_observer.h"
#include "net/log/net_log.h"
#include "net/url_request/url_request_context.h"
class NetLogController {
public:
NetLogController(net::URLRequestContext* url_request_context);
virtual ~NetLogController();
void Start();
void Stop();
private:
net::URLRequestContext* url_request_context_ = nullptr;
std::unique_ptr<net::FileNetLogObserver> file_net_log_observer_;
DISALLOW_COPY_AND_ASSIGN(NetLogController);
};
#endif // NET_LOG_CONTROLLER_H_
--------------------------------------------------------------------
net_log_controller.h 文件内容:
#include "net_log_controller.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_util.h"
NetLogController::NetLogController(net::URLRequestContext* url_request_context)
: url_request_context_(url_request_context) {}
NetLogController::~NetLogController() {}
void NetLogController::Start() {
base::FilePath log_path;
base::PathService::Get(base::DIR_EXE, &log_path);
log_path = log_path.AppendASCII("netlog.json");
if (base::PathExists(log_path)) {
base::DeleteFile(log_path, false);
}
std::unique_ptr<base::DictionaryValue> constants_dict =
net::GetNetConstants();
file_net_log_observer_ = net::FileNetLogObserver::CreateUnbounded(
log_path, std::move(constants_dict));
file_net_log_observer_->StartObserving(url_request_context_->net_log(),
net::NetLogCaptureMode::Default());
}
void NetLogController::Stop() {
if (!file_net_log_observer_)
return;
std::unique_ptr<base::DictionaryValue> net_info =
net::GetNetInfo(url_request_context_, net::NET_INFO_ALL_SOURCES);
file_net_log_observer_->StopObserving(std::move(net_info), base::Closure());
file_net_log_observer_.reset();
}
创建 FileNetLogObserver 时, 通过 net::GetNetConstants()
拿到的数据其实就是 NetLog 数据文件中的 constants。
通过 NetLogCaptureMode 参数,我们可以控制记录数据的详细程序。
FileNetLogObserver StopObserving
时通过 net::GetNetInfo(url_request_context_, net::NET_INFO_ALL_SOURCES);
拿到的数据其实就是 NetLog 数据文件中的 polledData。
NetLogWithSource
NetLog中的事件数据都是有数据源的。数据源真正产生事件数据时,调用 NetLogWithSource 去写数据。