Bug 1357682 - Part 2, add telemetry for HTTPChannelChild OMT success/fail rate and reason. r=mcmanus data-r=bsmedberg draft
authorShih-Chiang Chien <schien@mozilla.com>
Tue, 11 Jul 2017 14:52:35 +0800
changeset 608271 3cce84331920e285ec3f045a4e836bc9e1ff5ade
parent 608270 446543601e9234da25d292018d8a6e8a7ac7ba22
child 637255 278ab393a36f183e922dfea086b51cd437b165df
push id68223
push userschien@mozilla.com
push dateThu, 13 Jul 2017 10:51:36 +0000
reviewersmcmanus
bugs1357682
milestone56.0a1
Bug 1357682 - Part 2, add telemetry for HTTPChannelChild OMT success/fail rate and reason. r=mcmanus data-r=bsmedberg In order to identify how HTTP OMT is used in user environment, I add a telemetry HTTP_CHILD_OMT_STATS to record the success and fail reason for each HttpChannelChild. - "success": OMT request is accepted and the target thread is not main thread. - "successMainThread": OMT request is accepted but the target thread is still main thread. - "failListener": OMT request is rejected by the direct listener of this channel. - "failListenerChain": OMT request is rejected by one of the listener in the listener chain. - "notRequested": HTTP OMT is not requested by the channel owner. MozReview-Commit-ID: 1Gif1oteOOh
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
toolkit/components/telemetry/Histograms.json
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -20,16 +20,17 @@
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/net/HttpChannelChild.h"
 
 #include "AltDataOutputStreamChild.h"
 #include "HttpBackgroundChannelChild.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsPrimitives.h"
 #include "nsChannelClassifier.h"
+#include "nsContentPolicyUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsStringStream.h"
 #include "nsHttpChannel.h"
 #include "nsHttpHandler.h"
 #include "nsNetUtil.h"
 #include "nsSerializationHelper.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Performance.h"
@@ -1100,16 +1101,39 @@ HttpChannelChild::DoPreOnStopRequest(nsr
 {
   LOG(("HttpChannelChild::DoPreOnStopRequest [this=%p status=%" PRIx32 "]\n",
        this, static_cast<uint32_t>(aStatus)));
   mIsPending = false;
 
   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
     mStatus = aStatus;
   }
+
+  CollectOMTTelemetry();
+}
+
+void
+HttpChannelChild::CollectOMTTelemetry()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // Only collect telemetry for HTTP channel that is loaded successfully and
+  // completely.
+  if (mCanceled || NS_FAILED(mStatus)) {
+    return;
+  }
+
+  // Use content policy type to accumulate data by usage.
+  nsContentPolicyType type = mLoadInfo ?
+                             mLoadInfo->InternalContentPolicyType() :
+                             nsIContentPolicy::TYPE_OTHER;
+
+  nsAutoCString key(NS_CP_ContentTypeName(type));
+
+  Telemetry::AccumulateCategoricalKeyed(key, mOMTResult);
 }
 
 void
 HttpChannelChild::DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus, nsISupports* aContext)
 {
   LOG(("HttpChannelChild::DoOnStopRequest [this=%p]\n", this));
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mIsPending);
@@ -3256,39 +3280,44 @@ HttpChannelChild::RetargetDeliveryTo(nsI
 
   MOZ_ASSERT(NS_IsMainThread(), "Should be called on main thread only");
   MOZ_ASSERT(!mODATarget);
   MOZ_ASSERT(aNewTarget);
 
   NS_ENSURE_ARG(aNewTarget);
   if (aNewTarget->IsOnCurrentThread()) {
     NS_WARNING("Retargeting delivery to same thread");
+    mOMTResult = LABELS_HTTP_CHILD_OMT_STATS::successMainThread;
     return NS_OK;
   }
 
   // Ensure that |mListener| and any subsequent listeners can be retargeted
   // to another thread.
   nsresult rv = NS_OK;
   nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
       do_QueryInterface(mListener, &rv);
   if (!retargetableListener || NS_FAILED(rv)) {
     NS_WARNING("Listener is not retargetable");
+    mOMTResult = LABELS_HTTP_CHILD_OMT_STATS::failListener;
     return NS_ERROR_NO_INTERFACE;
   }
 
   rv = retargetableListener->CheckListenerChain();
   if (NS_FAILED(rv)) {
     NS_WARNING("Subsequent listeners are not retargetable");
+    mOMTResult = LABELS_HTTP_CHILD_OMT_STATS::failListenerChain;
     return rv;
   }
 
   {
     MutexAutoLock lock(mEventTargetMutex);
     mODATarget = aNewTarget;
   }
+
+  mOMTResult = LABELS_HTTP_CHILD_OMT_STATS::success;
   return NS_OK;
 }
 
 void
 HttpChannelChild::ResetInterception()
 {
   NS_ENSURE_TRUE_VOID(gNeckoChild != nullptr);
 
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -4,16 +4,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_net_HttpChannelChild_h
 #define mozilla_net_HttpChannelChild_h
 
 #include "mozilla/Mutex.h"
+#include "mozilla/Telemetry.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/net/HttpBaseChannel.h"
 #include "mozilla/net/NeckoTargetHolder.h"
 #include "mozilla/net/PHttpChannelChild.h"
 #include "mozilla/net/ChannelEventQueue.h"
 
 #include "nsIStreamListener.h"
 #include "nsILoadGroup.h"
@@ -29,16 +30,18 @@
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIAssociatedContentSecurity.h"
 #include "nsIChildChannel.h"
 #include "nsIHttpChannelChild.h"
 #include "nsIDivertableChannel.h"
 #include "nsIThreadRetargetableRequest.h"
 #include "mozilla/net/DNS.h"
 
+using mozilla::Telemetry::LABELS_HTTP_CHILD_OMT_STATS;
+
 class nsIEventTarget;
 class nsInputStreamPump;
 
 namespace mozilla {
 namespace net {
 
 class HttpBackgroundChannelChild;
 class InterceptedChannelContent;
@@ -414,16 +417,23 @@ private:
 
   // Perform a redirection without communicating with the parent process at all.
   void BeginNonIPCRedirect(nsIURI* responseURI,
                            const nsHttpResponseHead* responseHead);
 
   // Override the default security info pointer during a non-IPC redirection.
   void OverrideSecurityInfoForNonIPCRedirect(nsISupports* securityInfo);
 
+  // Collect telemetry for the successful rate of OMT.
+  void CollectOMTTelemetry();
+
+  // The result of RetargetDeliveryTo for this channel.
+  // |notRequested| represents OMT is not requested by the channel owner.
+  LABELS_HTTP_CHILD_OMT_STATS mOMTResult = LABELS_HTTP_CHILD_OMT_STATS::notRequested;
+
   friend class AssociateApplicationCacheEvent;
   friend class StartRequestEvent;
   friend class StopRequestEvent;
   friend class TransportAndDataEvent;
   friend class MaybeDivertOnDataHttpEvent;
   friend class MaybeDivertOnStopHttpEvent;
   friend class ProgressEvent;
   friend class StatusEvent;
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -2477,16 +2477,26 @@
     "alert_emails": ["rbarnes@mozilla.com"],
     "bug_numbers": [1266571],
     "expires_in_version": "52",
     "kind": "enumerated",
     "n_values": 8,
     "releaseChannelCollection": "opt-out",
     "description": "Recorded once for each HTTP 401 response. The value records the type of authentication and the TLS-enabled status. (0=basic/clear, 1=basic/tls, 2=digest/clear, 3=digest/tls, 4=ntlm/clear, 5=ntlm/tls, 6=negotiate/clear, 7=negotiate/tls)"
   },
+  "HTTP_CHILD_OMT_STATS": {
+    "record_in_processes": ["content"],
+    "alert_emails": ["necko@mozilla.com"],
+    "bug_numbers": [1357682],
+    "expires_in_version": "61",
+    "kind": "categorical",
+    "keyed": true,
+    "description": "Stats about success rate of HTTP OMT request in content process, keyed by content policy.",
+    "labels": ["success", "successMainThread", "failListener", "failListenerChain", "notRequested"]
+  },
   "TCP_FAST_OPEN": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "61",
     "kind": "enumerated",
     "n_values": 8,
     "description": "When a http connection is closed, track whether or not TCP Fast Open was used: 0=TFO_NOT_TRIED, 1=TFO_TRIED_NEGOTIATING, 2=TFO_DATA_SENT, 3=TFO_FAILED.",
     "alert_emails": ["necko@mozilla.com"],
     "bug_numbers": [1352271]