Add logging host lookups made by TurnPort to the RtcEventLog.

The following fields are logged:
- error, if there was an error.
- elapsed time in milliseconds

BUG=webrtc:8100

Review-Url: https://codereview.webrtc.org/2996933003
Cr-Original-Commit-Position: refs/heads/master@{#19574}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: c251cb13c08aba710ba3a12588beb4aa172c7323
diff --git a/logging/rtc_event_log/mock/mock_rtc_event_log.h b/logging/rtc_event_log/mock/mock_rtc_event_log.h
index cb31d8f..bd0753a 100644
--- a/logging/rtc_event_log/mock/mock_rtc_event_log.h
+++ b/logging/rtc_event_log/mock/mock_rtc_event_log.h
@@ -76,6 +76,10 @@
   MOCK_METHOD2(LogProbeResultSuccess, void(int id, int bitrate_bps));
   MOCK_METHOD2(LogProbeResultFailure,
                void(int id, ProbeFailureReason failure_reason));
+
+  MOCK_METHOD2(LogHostLookupResult,
+               void(int error,
+                    int64_t time_ms));
 };
 
 }  // namespace webrtc
diff --git a/logging/rtc_event_log/rtc_event_log.cc b/logging/rtc_event_log/rtc_event_log.cc
index e661e67..8e39c4a 100644
--- a/logging/rtc_event_log/rtc_event_log.cc
+++ b/logging/rtc_event_log/rtc_event_log.cc
@@ -94,6 +94,9 @@
   void LogProbeResultFailure(int id,
                              ProbeFailureReason failure_reason) override;
 
+  void LogHostLookupResult(int error,
+                           int64_t elapsed_time_in_milliseconds) override;
+
  private:
   // Private constructor to ensure that creation is done by RtcEventLog::Create.
   RtcEventLogImpl();
@@ -565,6 +568,18 @@
   StoreEvent(std::move(event));
 }
 
+void RtcEventLogImpl::LogHostLookupResult(
+    int error,
+    int64_t host_lookup_time_ms) {
+  std::unique_ptr<rtclog::Event> event(new rtclog::Event());
+  event->set_timestamp_us(rtc::TimeMicros());
+  event->set_type(rtclog::Event::HOST_LOOKUP_EVENT);
+  auto result = event->mutable_host_lookup_result();
+  result->set_error(error);
+  result->set_host_lookup_time_ms(host_lookup_time_ms);
+  StoreEvent(std::move(event));
+}
+
 void RtcEventLogImpl::StoreEvent(std::unique_ptr<rtclog::Event> event) {
   RTC_DCHECK(event.get() != nullptr);
   if (!event_queue_.Insert(&event)) {
diff --git a/logging/rtc_event_log/rtc_event_log.h b/logging/rtc_event_log/rtc_event_log.h
index dc33511..8e1ec21 100644
--- a/logging/rtc_event_log/rtc_event_log.h
+++ b/logging/rtc_event_log/rtc_event_log.h
@@ -170,6 +170,13 @@
   virtual void LogProbeResultFailure(int id,
                                      ProbeFailureReason failure_reason) = 0;
 
+  // Logs the result of a host lookup.
+  // if error =  0 - no error
+  //    error = -1 - generic error
+  //    else       - is given by underlying resolver
+  virtual void LogHostLookupResult(int error,
+                                   int64_t elapsed_time_in_milliseconds) = 0;
+
   // Reads an RtcEventLog file and returns true when reading was successful.
   // The result is stored in the given EventStream object.
   // The order of the events in the EventStream is implementation defined.
@@ -224,6 +231,9 @@
   void LogProbeResultSuccess(int id, int bitrate_bps) override{};
   void LogProbeResultFailure(int id,
                              ProbeFailureReason failure_reason) override{};
+
+  void LogHostLookupResult(int error,
+                           int64_t elapsed_time_in_milliseconds) override {}
 };
 
 }  // namespace webrtc
diff --git a/logging/rtc_event_log/rtc_event_log.proto b/logging/rtc_event_log/rtc_event_log.proto
index b9053ae..fac78dc 100644
--- a/logging/rtc_event_log/rtc_event_log.proto
+++ b/logging/rtc_event_log/rtc_event_log.proto
@@ -40,6 +40,7 @@
     AUDIO_NETWORK_ADAPTATION_EVENT = 16;
     BWE_PROBE_CLUSTER_CREATED_EVENT = 17;
     BWE_PROBE_RESULT_EVENT = 18;
+    HOST_LOOKUP_EVENT = 19;
   }
 
   // required - Indicates the type of this event
@@ -81,6 +82,9 @@
 
     // required if type == BWE_PROBE_RESULT_EVENT
     BweProbeResult probe_result = 18;
+
+    // required if type == HOST_LOOKUP_EVENT
+    HostLookupResult host_lookup_result = 19;
   }
 }
 
@@ -314,3 +318,12 @@
   // optional - but required if result == SUCCESS. The resulting bitrate in bps.
   optional uint64 bitrate_bps = 3;
 }
+
+message HostLookupResult {
+  // required - error code or 0 for OK
+  optional int32 error = 1;
+
+  // required - Time elapsed for lookup in milliseconds.
+  optional int64 host_lookup_time_ms = 2;
+}
+
diff --git a/logging/rtc_event_log/rtc_event_log2stats.cc b/logging/rtc_event_log/rtc_event_log2stats.cc
index 6b21cf1..3461791 100644
--- a/logging/rtc_event_log/rtc_event_log2stats.cc
+++ b/logging/rtc_event_log/rtc_event_log2stats.cc
@@ -160,6 +160,8 @@
       return "BWE_PROBE_CREATED";
     case webrtc::rtclog::Event::BWE_PROBE_RESULT_EVENT:
       return "BWE_PROBE_RESULT";
+    case webrtc::rtclog::Event::HOST_LOOKUP_EVENT:
+      return "HOST_LOOKUP";
   }
   RTC_NOTREACHED();
   return "UNKNOWN_EVENT";
diff --git a/logging/rtc_event_log/rtc_event_log2text.cc b/logging/rtc_event_log/rtc_event_log2text.cc
index c7214e2..763d40e 100644
--- a/logging/rtc_event_log/rtc_event_log2text.cc
+++ b/logging/rtc_event_log/rtc_event_log2text.cc
@@ -566,6 +566,17 @@
         }
       }
     }
+    if (parsed_stream.GetEventType(i) ==
+        webrtc::ParsedRtcEventLog::HOST_LOOKUP_EVENT) {
+      int error;
+      int64_t elapsed_ms;
+      parsed_stream.GetHostLookup(i, &error, &elapsed_ms);
+      std::cout << parsed_stream.GetTimestamp(i)
+                << "\tHOST_LOOKUP"
+                << "\terror=" << error
+                << "\telapsed_ms=" << elapsed_ms
+                << std::endl;
+    }
   }
   return 0;
 }
diff --git a/logging/rtc_event_log/rtc_event_log_parser.cc b/logging/rtc_event_log/rtc_event_log_parser.cc
index a7237ee..2960edd 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -74,6 +74,8 @@
       return ParsedRtcEventLog::EventType::BWE_PROBE_CLUSTER_CREATED_EVENT;
     case rtclog::Event::BWE_PROBE_RESULT_EVENT:
       return ParsedRtcEventLog::EventType::BWE_PROBE_RESULT_EVENT;
+    case rtclog::Event::HOST_LOOKUP_EVENT:
+      return ParsedRtcEventLog::EventType::HOST_LOOKUP_EVENT;
   }
   RTC_NOTREACHED();
   return ParsedRtcEventLog::EventType::UNKNOWN_EVENT;
@@ -654,4 +656,21 @@
   }
   return MediaType::ANY;
 }
+
+void ParsedRtcEventLog::GetHostLookup(
+    size_t index,
+    int* error, int64_t* host_lookup_time_ms) const {
+  RTC_CHECK_LT(index, GetNumberOfEvents());
+  const rtclog::Event& event = events_[index];
+  RTC_CHECK(event.has_type());
+  RTC_CHECK_EQ(event.type(), rtclog::Event::HOST_LOOKUP_EVENT);
+  RTC_CHECK(event.has_host_lookup_result());
+  const rtclog::HostLookupResult& lookup_event = event.host_lookup_result();
+  RTC_CHECK(lookup_event.has_error());
+  if (error)
+    *error = lookup_event.error();
+  RTC_CHECK(lookup_event.has_host_lookup_time_ms());
+  if (host_lookup_time_ms)
+    *host_lookup_time_ms = lookup_event.host_lookup_time_ms();
+}
 }  // namespace webrtc
diff --git a/logging/rtc_event_log/rtc_event_log_parser.h b/logging/rtc_event_log/rtc_event_log_parser.h
index 1c2390b..fef912f 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.h
+++ b/logging/rtc_event_log/rtc_event_log_parser.h
@@ -75,7 +75,8 @@
     AUDIO_SENDER_CONFIG_EVENT = 11,
     AUDIO_NETWORK_ADAPTATION_EVENT = 16,
     BWE_PROBE_CLUSTER_CREATED_EVENT = 17,
-    BWE_PROBE_RESULT_EVENT = 18
+    BWE_PROBE_RESULT_EVENT = 18,
+    HOST_LOOKUP_EVENT = 19
   };
 
   enum class MediaType { ANY, AUDIO, VIDEO, DATA };
@@ -174,6 +175,10 @@
 
   MediaType GetMediaType(uint32_t ssrc, PacketDirection direction) const;
 
+  // Reads info from a HostLookupResult.
+  void GetHostLookup(size_t index,
+                     int* error, int64_t* host_lookup_time_ms) const;
+
  private:
   rtclog::StreamConfig GetVideoReceiveConfig(const rtclog::Event& event) const;
   std::vector<rtclog::StreamConfig> GetVideoSendConfig(
diff --git a/logging/rtc_event_log/rtc_event_log_unittest.cc b/logging/rtc_event_log/rtc_event_log_unittest.cc
index e908ccd..7c661fa 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest.cc
@@ -873,4 +873,53 @@
   test.DoTest();
 }
 
+TEST(RtcEventLogTest, LogHostLookupResult) {
+  unsigned int random_seed = 779911;
+  Random prng(random_seed);
+
+  // Find the name of the current test, in order to use it as a temporary
+  // filename.
+  auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
+  const std::string temp_filename =
+      test::OutputPath() + test_info->test_case_name() + test_info->name();
+
+  // When log_dumper goes out of scope, it causes the log file to be flushed
+  // to disk.
+  {
+    rtc::ScopedFakeClock fake_clock;
+    fake_clock.SetTimeMicros(prng.Rand<uint32_t>());
+    std::unique_ptr<RtcEventLog> log_dumper(RtcEventLog::Create());
+    log_dumper->StartLogging(temp_filename, 10000000);
+    fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000));
+    log_dumper->LogHostLookupResult(0, 123);
+    fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000));
+    log_dumper->LogHostLookupResult(1, 349);
+    fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000));
+    log_dumper->StopLogging();
+  }
+
+  // Read the generated file from disk.
+  ParsedRtcEventLog parsed_log;
+
+  ASSERT_TRUE(parsed_log.ParseFile(temp_filename));
+
+  // Verify that what we read back from the event log is the same as
+  // what we wrote down. For RTCP we log the full packets, but for
+  // RTP we should only log the header.
+  const size_t event_count = 4;
+  EXPECT_EQ(event_count, parsed_log.GetNumberOfEvents());
+  if (event_count != parsed_log.GetNumberOfEvents()) {
+    // Print the expected and actual event types for easier debugging.
+    PrintActualEvents(parsed_log);
+  }
+
+  RtcEventLogTestHelper::VerifyLogStartEvent(parsed_log, 0);
+  RtcEventLogTestHelper::VerifyLogHostLookupEvent(parsed_log, 1, 0, 123);
+  RtcEventLogTestHelper::VerifyLogHostLookupEvent(parsed_log, 2, 1, 349);
+  RtcEventLogTestHelper::VerifyLogEndEvent(parsed_log, 3);
+
+  // Clean up temporary file - can be pretty slow.
+  remove(temp_filename.c_str());
+}
+
 }  // namespace webrtc
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
index 9d98855..969b934 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -570,4 +570,26 @@
   // TODO(philipel): Verify the parser when parsing has been implemented.
 }
 
+void RtcEventLogTestHelper::VerifyLogHostLookupEvent(
+    const ParsedRtcEventLog& parsed_log,
+    size_t index,
+    int error,
+    int64_t host_lookup_time_ms) {
+  const rtclog::Event& event = parsed_log.events_[index];
+  ASSERT_TRUE(IsValidBasicEvent(event));
+  EXPECT_EQ(rtclog::Event::HOST_LOOKUP_EVENT, event.type());
+
+  const rtclog::HostLookupResult& lookup_event = event.host_lookup_result();
+  ASSERT_TRUE(lookup_event.has_error());
+  ASSERT_EQ(lookup_event.error(), error);
+  ASSERT_TRUE(lookup_event.has_host_lookup_time_ms());
+  ASSERT_EQ(lookup_event.host_lookup_time_ms(), host_lookup_time_ms);
+
+  int error_compare;
+  int64_t host_lookup_time_ms_compare;
+  parsed_log.GetHostLookup(index, &error_compare, &host_lookup_time_ms_compare);
+  ASSERT_EQ(error, error_compare);
+  ASSERT_EQ(host_lookup_time_ms, host_lookup_time_ms_compare);
+}
+
 }  // namespace webrtc
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
index 04aa6bf..fb13476 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.h
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
@@ -82,6 +82,11 @@
                                        size_t index,
                                        uint32_t id,
                                        ProbeFailureReason failure_reason);
+
+  static void VerifyLogHostLookupEvent(const ParsedRtcEventLog& parsed_log,
+                                       size_t index,
+                                       int error,
+                                       int64_t host_lookup_time_ms);
 };
 
 }  // namespace webrtc
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index 588f6bd..1680056 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -87,6 +87,7 @@
   deps = [
     "../api:libjingle_peerconnection_api",
     "../api:ortc_api",
+    "../logging:rtc_event_log_api",
     "../rtc_base:rtc_base",
     "../system_wrappers:field_trial_api",
   ]
diff --git a/p2p/DEPS b/p2p/DEPS
index 161835f..39cc8b2 100644
--- a/p2p/DEPS
+++ b/p2p/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+net",
   "+webrtc/base",
+  "+webrtc/logging",
   "+webrtc/system_wrappers",
 ]
diff --git a/p2p/base/port_unittest.cc b/p2p/base/port_unittest.cc
index 757c1b3..59b8f02 100644
--- a/p2p/base/port_unittest.cc
+++ b/p2p/base/port_unittest.cc
@@ -533,10 +533,14 @@
                            PacketSocketFactory* socket_factory,
                            ProtocolType int_proto, ProtocolType ext_proto,
                            const rtc::SocketAddress& server_addr) {
-    return TurnPort::Create(&main_, socket_factory, MakeNetwork(addr), 0, 0,
+    constexpr uint16_t kMinPort = 0;
+    constexpr uint16_t kMaxPort = 0;
+    webrtc::RtcEventLog* event_log = nullptr;
+    return TurnPort::Create(&main_, socket_factory, MakeNetwork(addr),
+                            kMinPort, kMaxPort,
                             username_, password_,
                             ProtocolAddress(server_addr, int_proto),
-                            kRelayCredentials, 0, std::string());
+                            kRelayCredentials, 0, std::string(), event_log);
   }
   RelayPort* CreateGturnPort(const SocketAddress& addr,
                              ProtocolType int_proto, ProtocolType ext_proto) {
diff --git a/p2p/base/turnport.cc b/p2p/base/turnport.cc
index 4dfe06d..c1872df 100644
--- a/p2p/base/turnport.cc
+++ b/p2p/base/turnport.cc
@@ -13,6 +13,7 @@
 #include <algorithm>
 #include <functional>
 
+#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
 #include "webrtc/p2p/base/common.h"
 #include "webrtc/p2p/base/stun.h"
 #include "webrtc/rtc_base/asyncpacketsocket.h"
@@ -190,13 +191,9 @@
                    const ProtocolAddress& server_address,
                    const RelayCredentials& credentials,
                    int server_priority,
-                   const std::string& origin)
-    : Port(thread,
-           RELAY_PORT_TYPE,
-           factory,
-           network,
-           username,
-           password),
+                   const std::string& origin,
+                   webrtc::RtcEventLog* event_log)
+    : Port(thread, RELAY_PORT_TYPE, factory, network, username, password),
       server_address_(server_address),
       credentials_(credentials),
       socket_(socket),
@@ -206,7 +203,8 @@
       next_channel_number_(TURN_CHANNEL_NUMBER_START),
       state_(STATE_CONNECTING),
       server_priority_(server_priority),
-      allocate_mismatch_retries_(0) {
+      allocate_mismatch_retries_(0),
+      event_log_(event_log) {
   request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
   request_manager_.set_origin(origin);
 }
@@ -221,7 +219,8 @@
                    const ProtocolAddress& server_address,
                    const RelayCredentials& credentials,
                    int server_priority,
-                   const std::string& origin)
+                   const std::string& origin,
+                   webrtc::RtcEventLog* event_log)
     : Port(thread,
            RELAY_PORT_TYPE,
            factory,
@@ -239,7 +238,8 @@
       next_channel_number_(TURN_CHANNEL_NUMBER_START),
       state_(STATE_CONNECTING),
       server_priority_(server_priority),
-      allocate_mismatch_retries_(0) {
+      allocate_mismatch_retries_(0),
+      event_log_(event_log) {
   request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
   request_manager_.set_origin(origin);
 }
@@ -709,15 +709,32 @@
   // Copy the original server address in |resolved_address|. For TLS based
   // sockets we need hostname along with resolved address.
   rtc::SocketAddress resolved_address = server_address_.address;
-  if (resolver_->GetError() != 0 ||
-      !resolver_->GetResolvedAddress(Network()->GetBestIP().family(),
-                                     &resolved_address)) {
-    LOG_J(LS_WARNING, this) << "TURN host lookup received error "
-                            << resolver_->GetError();
+
+  bool found = resolver_->GetError() == 0 &&
+               resolver_->GetResolvedAddress(Network()->GetBestIP().family(),
+                                             &resolved_address);
+  if (event_log_) {
+    int error = resolver_->GetError();
+    event_log_->LogHostLookupResult(
+        found ? 0 : (error == 0 ? -1 : error),
+        resolver_->GetResolveElapsedTimeMilliseconds());
+  }
+
+  if (!found) {
+    LOG_J(LS_WARNING, this)
+        << "TURN host lookup for " << resolved_address.hostname()
+        << " received error " << resolver_->GetError() << " after "
+        << resolver_->GetResolveElapsedTimeMilliseconds() << " ms";
     error_ = resolver_->GetError();
     OnAllocateError();
     return;
   }
+
+  LOG_J(LS_INFO, this) << "TURN host lookup for " << resolved_address.hostname()
+                       << " completed in "
+                       << resolver_->GetResolveElapsedTimeMilliseconds()
+                       << " ms";
+
   // Signal needs both resolved and unresolved address. After signal is sent
   // we can copy resolved address back into |server_address_|.
   SignalResolvedServerAddress(this, server_address_.address,
diff --git a/p2p/base/turnport.h b/p2p/base/turnport.h
index abdaa3d..8127669 100644
--- a/p2p/base/turnport.h
+++ b/p2p/base/turnport.h
@@ -52,9 +52,11 @@
                           const ProtocolAddress& server_address,
                           const RelayCredentials& credentials,
                           int server_priority,
-                          const std::string& origin) {
+                          const std::string& origin,
+                          webrtc::RtcEventLog* event_log) {
     return new TurnPort(thread, factory, network, socket, username, password,
-                        server_address, credentials, server_priority, origin);
+                        server_address, credentials, server_priority, origin,
+                        event_log);
   }
 
   // Create a TURN port that will use a new socket, bound to |network| and
@@ -69,10 +71,11 @@
                           const ProtocolAddress& server_address,
                           const RelayCredentials& credentials,
                           int server_priority,
-                          const std::string& origin) {
+                          const std::string& origin,
+                          webrtc::RtcEventLog* event_log) {
     return new TurnPort(thread, factory, network, min_port, max_port, username,
                         password, server_address, credentials, server_priority,
-                        origin);
+                        origin, event_log);
   }
 
   virtual ~TurnPort();
@@ -174,7 +177,8 @@
            const ProtocolAddress& server_address,
            const RelayCredentials& credentials,
            int server_priority,
-           const std::string& origin);
+           const std::string& origin,
+           webrtc::RtcEventLog* event_log);
 
   TurnPort(rtc::Thread* thread,
            rtc::PacketSocketFactory* factory,
@@ -186,7 +190,8 @@
            const ProtocolAddress& server_address,
            const RelayCredentials& credentials,
            int server_priority,
-           const std::string& origin);
+           const std::string& origin,
+           webrtc::RtcEventLog* event_log);
 
  private:
   enum {
@@ -290,6 +295,8 @@
   // The number of retries made due to allocate mismatch error.
   size_t allocate_mismatch_retries_;
 
+  webrtc::RtcEventLog* event_log_;
+
   rtc::AsyncInvoker invoker_;
 
   friend class TurnEntry;
diff --git a/p2p/base/turnport_unittest.cc b/p2p/base/turnport_unittest.cc
index 7c6f72b..50356ee 100644
--- a/p2p/base/turnport_unittest.cc
+++ b/p2p/base/turnport_unittest.cc
@@ -261,9 +261,10 @@
                                    const ProtocolAddress& server_address,
                                    const std::string& origin) {
     RelayCredentials credentials(username, password);
+    webrtc::RtcEventLog* event_log = nullptr;
     turn_port_.reset(TurnPort::Create(&main_, &socket_factory_, network, 0, 0,
                                       kIceUfrag1, kIcePwd1, server_address,
-                                      credentials, 0, origin));
+                                      credentials, 0, origin, event_log));
     // This TURN port will be the controlling.
     turn_port_->SetIceRole(ICEROLE_CONTROLLING);
     ConnectSignals();
@@ -291,9 +292,11 @@
     }
 
     RelayCredentials credentials(username, password);
-    turn_port_.reset(TurnPort::Create(
-        &main_, &socket_factory_, MakeNetwork(kLocalAddr1), socket_.get(),
-        kIceUfrag1, kIcePwd1, server_address, credentials, 0, std::string()));
+    webrtc::RtcEventLog* event_log = nullptr;
+    turn_port_.reset(
+        TurnPort::Create(&main_, &socket_factory_, MakeNetwork(kLocalAddr1),
+                         socket_.get(), kIceUfrag1, kIcePwd1, server_address,
+                         credentials, 0, std::string(), event_log));
     // This TURN port will be the controlling.
     turn_port_->SetIceRole(ICEROLE_CONTROLLING);
     ConnectSignals();
diff --git a/p2p/client/basicportallocator.cc b/p2p/client/basicportallocator.cc
index 66ee9a4..051ef84 100644
--- a/p2p/client/basicportallocator.cc
+++ b/p2p/client/basicportallocator.cc
@@ -98,15 +98,19 @@
 
 // BasicPortAllocator
 BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager,
-                                       rtc::PacketSocketFactory* socket_factory)
-    : network_manager_(network_manager), socket_factory_(socket_factory) {
+                                       rtc::PacketSocketFactory* socket_factory,
+                                       webrtc::RtcEventLog* event_log)
+    : network_manager_(network_manager),
+      socket_factory_(socket_factory),
+      event_log_(event_log) {
   RTC_DCHECK(network_manager_ != nullptr);
   RTC_DCHECK(socket_factory_ != nullptr);
   Construct();
 }
 
 BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager)
-    : network_manager_(network_manager), socket_factory_(nullptr) {
+    : network_manager_(network_manager), socket_factory_(nullptr),
+      event_log_(nullptr) {
   RTC_DCHECK(network_manager_ != nullptr);
   Construct();
 }
@@ -114,7 +118,8 @@
 BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager,
                                        rtc::PacketSocketFactory* socket_factory,
                                        const ServerAddresses& stun_servers)
-    : network_manager_(network_manager), socket_factory_(socket_factory) {
+    : network_manager_(network_manager), socket_factory_(socket_factory),
+      event_log_(nullptr) {
   RTC_DCHECK(socket_factory_ != NULL);
   SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0, false);
   Construct();
@@ -126,7 +131,8 @@
     const rtc::SocketAddress& relay_address_udp,
     const rtc::SocketAddress& relay_address_tcp,
     const rtc::SocketAddress& relay_address_ssl)
-    : network_manager_(network_manager), socket_factory_(NULL) {
+    : network_manager_(network_manager), socket_factory_(NULL),
+      event_log_(nullptr) {
   std::vector<RelayServerConfig> turn_servers;
   RelayServerConfig config(RELAY_GTURN);
   if (!relay_address_udp.IsNil()) {
@@ -1429,12 +1435,11 @@
     // due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
     if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
         relay_port->proto == PROTO_UDP && udp_socket_) {
-      port = TurnPort::Create(session_->network_thread(),
-                              session_->socket_factory(),
-                              network_, udp_socket_.get(),
-                              session_->username(), session_->password(),
-                              *relay_port, config.credentials, config.priority,
-                              session_->allocator()->origin());
+      port = TurnPort::Create(
+          session_->network_thread(), session_->socket_factory(), network_,
+          udp_socket_.get(), session_->username(), session_->password(),
+          *relay_port, config.credentials, config.priority,
+          session_->allocator()->origin(), session_->event_log());
       turn_ports_.push_back(port);
       // Listen to the port destroyed signal, to allow AllocationSequence to
       // remove entrt from it's map.
@@ -1444,7 +1449,8 @@
           session_->network_thread(), session_->socket_factory(), network_,
           session_->allocator()->min_port(), session_->allocator()->max_port(),
           session_->username(), session_->password(), *relay_port,
-          config.credentials, config.priority, session_->allocator()->origin());
+          config.credentials, config.priority, session_->allocator()->origin(),
+          session_->event_log());
     }
     RTC_DCHECK(port != NULL);
     port->SetTlsCertPolicy(config.tls_cert_policy);
diff --git a/p2p/client/basicportallocator.h b/p2p/client/basicportallocator.h
index 5a4999c..071d6f3 100644
--- a/p2p/client/basicportallocator.h
+++ b/p2p/client/basicportallocator.h
@@ -21,12 +21,17 @@
 #include "webrtc/rtc_base/network.h"
 #include "webrtc/rtc_base/thread.h"
 
+namespace webrtc {
+class RtcEventLog;
+}  // namespace webrtc
+
 namespace cricket {
 
 class BasicPortAllocator : public PortAllocator {
  public:
   BasicPortAllocator(rtc::NetworkManager* network_manager,
-                     rtc::PacketSocketFactory* socket_factory);
+                     rtc::PacketSocketFactory* socket_factory,
+                     webrtc::RtcEventLog* event_log);
   explicit BasicPortAllocator(rtc::NetworkManager* network_manager);
   BasicPortAllocator(rtc::NetworkManager* network_manager,
                      rtc::PacketSocketFactory* socket_factory,
@@ -49,6 +54,7 @@
   int network_ignore_mask() const { return network_ignore_mask_; }
 
   rtc::NetworkManager* network_manager() const { return network_manager_; }
+  webrtc::RtcEventLog* event_log() const { return event_log_; }
 
   // If socket_factory() is set to NULL each PortAllocatorSession
   // creates its own socket factory.
@@ -71,6 +77,7 @@
 
   rtc::NetworkManager* network_manager_;
   rtc::PacketSocketFactory* socket_factory_;
+  webrtc::RtcEventLog* event_log_;
   bool allow_tcp_listen_;
   int network_ignore_mask_ = rtc::kDefaultNetworkIgnoreMask;
 };
@@ -99,6 +106,7 @@
   virtual BasicPortAllocator* allocator() { return allocator_; }
   rtc::Thread* network_thread() { return network_thread_; }
   rtc::PacketSocketFactory* socket_factory() { return socket_factory_; }
+  webrtc::RtcEventLog* event_log() { return allocator_->event_log(); }
 
   void SetCandidateFilter(uint32_t filter) override;
   void StartGettingPorts() override;
diff --git a/pc/peerconnectionfactory.cc b/pc/peerconnectionfactory.cc
index be083c2..3d50146 100644
--- a/pc/peerconnectionfactory.cc
+++ b/pc/peerconnectionfactory.cc
@@ -252,19 +252,20 @@
         new rtc::RTCCertificateGenerator(signaling_thread_, network_thread_));
   }
 
-  if (!allocator) {
-    allocator.reset(new cricket::BasicPortAllocator(
-        default_network_manager_.get(), default_socket_factory_.get()));
-  }
-  network_thread_->Invoke<void>(
-      RTC_FROM_HERE, rtc::Bind(&cricket::PortAllocator::SetNetworkIgnoreMask,
-                               allocator.get(), options_.network_ignore_mask));
-
   std::unique_ptr<RtcEventLog> event_log(new RtcEventLogNullImpl());
   if (event_log_factory_) {
     event_log = event_log_factory_->CreateRtcEventLog();
   }
 
+  if (!allocator) {
+    allocator.reset(new cricket::BasicPortAllocator(
+        default_network_manager_.get(), default_socket_factory_.get(),
+        event_log.get()));
+  }
+  network_thread_->Invoke<void>(
+      RTC_FROM_HERE, rtc::Bind(&cricket::PortAllocator::SetNetworkIgnoreMask,
+                               allocator.get(), options_.network_ignore_mask));
+
   std::unique_ptr<Call> call = worker_thread_->Invoke<std::unique_ptr<Call>>(
       RTC_FROM_HERE,
       rtc::Bind(&PeerConnectionFactory::CreateCall_w, this, event_log.get()));
diff --git a/rtc_base/asyncresolverinterface.h b/rtc_base/asyncresolverinterface.h
index 7b8c533..1438042 100644
--- a/rtc_base/asyncresolverinterface.h
+++ b/rtc_base/asyncresolverinterface.h
@@ -37,6 +37,7 @@
     GetResolvedAddress(AF_INET, &addr);
     return addr;
   }
+  virtual int64_t GetResolveElapsedTimeMilliseconds() const = 0;
 
   // This signal is fired when address resolve process is completed.
   sigslot::signal1<AsyncResolverInterface*> SignalDone;
diff --git a/rtc_base/nethelpers.cc b/rtc_base/nethelpers.cc
index 8489970..e5e4ea6 100644
--- a/rtc_base/nethelpers.cc
+++ b/rtc_base/nethelpers.cc
@@ -84,7 +84,8 @@
 
 // AsyncResolver
 AsyncResolver::AsyncResolver()
-    : SignalThread(false /* use_socket_server */), error_(-1) {}
+    : SignalThread(false /* use_socket_server */),
+      error_(-1), resolve_time_ms_(0) {}
 
 AsyncResolver::~AsyncResolver() = default;
 
@@ -108,6 +109,10 @@
   return false;
 }
 
+int64_t AsyncResolver::GetResolveElapsedTimeMilliseconds() const {
+  return resolve_time_ms_;
+}
+
 int AsyncResolver::GetError() const {
   return error_;
 }
@@ -117,8 +122,11 @@
 }
 
 void AsyncResolver::DoWork() {
+  int64_t start = rtc::TimeMillis();
   error_ = ResolveHostname(addr_.hostname().c_str(), addr_.family(),
                            &addresses_);
+  int64_t stop = rtc::TimeMillis();
+  resolve_time_ms_ = stop - start;
 }
 
 void AsyncResolver::OnWorkDone() {
diff --git a/rtc_base/nethelpers.h b/rtc_base/nethelpers.h
index d25879e..5e5f6ac 100644
--- a/rtc_base/nethelpers.h
+++ b/rtc_base/nethelpers.h
@@ -40,6 +40,7 @@
   bool GetResolvedAddress(int family, SocketAddress* addr) const override;
   int GetError() const override;
   void Destroy(bool wait) override;
+  int64_t GetResolveElapsedTimeMilliseconds() const override;
 
   const std::vector<IPAddress>& addresses() const { return addresses_; }
   void set_error(int error) { error_ = error; }
@@ -52,6 +53,7 @@
   SocketAddress addr_;
   std::vector<IPAddress> addresses_;
   int error_;
+  int64_t resolve_time_ms_;
 };
 
 // rtc namespaced wrappers for inet_ntop and inet_pton so we can avoid
diff --git a/rtc_tools/event_log_visualizer/analyzer.cc b/rtc_tools/event_log_visualizer/analyzer.cc
index 4d485c7..5da9c34 100644
--- a/rtc_tools/event_log_visualizer/analyzer.cc
+++ b/rtc_tools/event_log_visualizer/analyzer.cc
@@ -509,6 +509,10 @@
         bwe_probe_result_events_.push_back(parsed_log_.GetBweProbeResult(i));
         break;
       }
+      case ParsedRtcEventLog::HOST_LOOKUP_EVENT: {
+        // TODO(jonaso): What to do ??
+        break;
+      }
       case ParsedRtcEventLog::UNKNOWN_EVENT: {
         break;
       }
diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc
index 5732e8e..8c7c88b 100644
--- a/voice_engine/channel.cc
+++ b/voice_engine/channel.cc
@@ -186,6 +186,11 @@
     }
   };
 
+  void LogHostLookupResult(int error,
+                           int64_t elapsed_time_in_milliseconds) override {
+    RTC_NOTREACHED();
+  }
+
   void SetEventLog(RtcEventLog* event_log) {
     rtc::CritScope lock(&crit_);
     event_log_ = event_log;