Bug 1436188 - Add telemetry probes to collect the number of failures during the QuotaManager initialization; r=asuth, data-review=chutten
authorTom Tung <shes050117@gmail.com>
Thu, 17 Jan 2019 17:12:27 +0000
changeset 511402 c0db84bf3f57f80a4911b83ab6c13525786ad69e
parent 511401 bbc57e229df64bdf5b4fa2d86bf419686bacf496
child 511403 cc0ec99ff8b8e36e50f31c257ea9463354c71e83
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1436188
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1436188 - Add telemetry probes to collect the number of failures during the QuotaManager initialization; r=asuth, data-review=chutten This patch uses categorical keyed Historgram to collect data. While the key is used to determine whether is it an external error or an internal error (Note: the external error is referred to low level failure, for example: database corrupt, OS API errors, ... etc; the internal error is referred to errors, like: not handle file properly, unexpected filenames, ... etc), the labels for categorical indicates where the error happens. Furthermore, this patch make QuotaManager keep traversing the profile even if an error happens so that we can get more information in the telemetry data. Please note that these things should only happen in the Nightly Channel. Differential Revision: https://phabricator.services.mozilla.com/D15908
dom/asmjscache/AsmJSCache.cpp
dom/cache/QuotaClient.cpp
dom/indexedDB/ActorsParent.cpp
dom/localstorage/ActorsParent.cpp
dom/quota/ActorsParent.cpp
dom/quota/QuotaCommon.h
dom/quota/QuotaManager.h
toolkit/components/telemetry/Histograms.json
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -13,24 +13,26 @@
 #include "jsfriendapi.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/CondVar.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h"
 #include "mozilla/dom/asmjscache/PAsmJSCacheEntryParent.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/quota/Client.h"
+#include "mozilla/dom/quota/QuotaCommon.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/QuotaObject.h"
 #include "mozilla/dom/quota/UsageInfo.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundChild.h"
+#include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "nsAutoPtr.h"
 #include "nsAtom.h"
 #include "nsIFile.h"
 #include "nsIPrincipal.h"
 #include "nsIRunnable.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIThread.h"
@@ -289,16 +291,23 @@ class Client : public quota::Client {
   void StartIdleMaintenance() override;
 
   void StopIdleMaintenance() override;
 
   void ShutdownWorkThreads() override;
 
  private:
   ~Client() override;
+
+  nsresult GetUsageForOriginInternal(PersistenceType aPersistenceType,
+                                     const nsACString& aGroup,
+                                     const nsACString& aOrigin,
+                                     const AtomicBool& aCanceled,
+                                     UsageInfo* aUsageInfo,
+                                     const bool aInitializing);
 };
 
 // FileDescriptorHolder owns a file descriptor and its memory mapping.
 // FileDescriptorHolder is derived by two runnable classes (that is,
 // (Parent|Child)Runnable.
 class FileDescriptorHolder : public Runnable {
  public:
   FileDescriptorHolder()
@@ -1661,71 +1670,27 @@ Client::Type Client::GetType() { return 
 
 nsresult Client::InitOrigin(PersistenceType aPersistenceType,
                             const nsACString& aGroup, const nsACString& aOrigin,
                             const AtomicBool& aCanceled,
                             UsageInfo* aUsageInfo) {
   if (!aUsageInfo) {
     return NS_OK;
   }
-  return GetUsageForOrigin(aPersistenceType, aGroup, aOrigin, aCanceled,
-                           aUsageInfo);
+  return GetUsageForOriginInternal(aPersistenceType, aGroup, aOrigin, aCanceled,
+                                   aUsageInfo, /* aInitializing */ true);
 }
 
 nsresult Client::GetUsageForOrigin(PersistenceType aPersistenceType,
                                    const nsACString& aGroup,
                                    const nsACString& aOrigin,
                                    const AtomicBool& aCanceled,
                                    UsageInfo* aUsageInfo) {
-  QuotaManager* qm = QuotaManager::Get();
-  MOZ_ASSERT(qm, "We were being called by the QuotaManager");
-
-  nsCOMPtr<nsIFile> directory;
-  nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin,
-                                          getter_AddRefs(directory));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  MOZ_ASSERT(directory, "We're here because the origin directory exists");
-
-  rv = directory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  DebugOnly<bool> exists;
-  MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists);
-
-  nsCOMPtr<nsIDirectoryEnumerator> entries;
-  rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  nsCOMPtr<nsIFile> file;
-  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
-         file && !aCanceled) {
-    int64_t fileSize;
-    rv = file->GetFileSize(&fileSize);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    MOZ_ASSERT(fileSize >= 0, "Negative size?!");
-
-    // Since the client is not explicitly storing files, append to database
-    // usage which represents implicit storage allocation.
-    aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
-  }
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  return NS_OK;
+  return GetUsageForOriginInternal(aPersistenceType, aGroup, aOrigin, aCanceled,
+                                   aUsageInfo, /* aInitializing */ false);
 }
 
 void Client::OnOriginClearCompleted(PersistenceType aPersistenceType,
                                     const nsACString& aOrigin) {}
 
 void Client::ReleaseIOThreadObjects() {}
 
 void Client::AbortOperations(const nsACString& aOrigin) {}
@@ -1742,16 +1707,82 @@ void Client::ShutdownWorkThreads() {
 
   mShutdownRequested = true;
 
   if (sLiveParentActors) {
     MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return !sLiveParentActors; }));
   }
 }
 
+nsresult Client::GetUsageForOriginInternal(PersistenceType aPersistenceType,
+                                           const nsACString& aGroup,
+                                           const nsACString& aOrigin,
+                                           const AtomicBool& aCanceled,
+                                           UsageInfo* aUsageInfo,
+                                           const bool aInitializing) {
+  QuotaManager* qm = QuotaManager::Get();
+  MOZ_ASSERT(qm, "We were being called by the QuotaManager");
+#ifndef NIGHTLY_BUILD
+  Unused << aInitializing;
+#endif
+
+  nsCOMPtr<nsIFile> directory;
+  nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin,
+                                          getter_AddRefs(directory));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                 Asm_GetDirForOrigin);
+    return rv;
+  }
+
+  MOZ_ASSERT(directory, "We're here because the origin directory exists");
+
+  rv = directory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError, Asm_Append);
+    return rv;
+  }
+
+  DebugOnly<bool> exists;
+  MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists);
+
+  nsCOMPtr<nsIDirectoryEnumerator> entries;
+  rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                 Asm_GetDirEntries);
+    return rv;
+  }
+
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
+         file && !aCanceled) {
+    int64_t fileSize;
+    rv = file->GetFileSize(&fileSize);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                   Asm_GetFileSize);
+      return rv;
+    }
+
+    MOZ_ASSERT(fileSize >= 0, "Negative size?!");
+
+    // Since the client is not explicitly storing files, append to database
+    // usage which represents implicit storage allocation.
+    aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
+  }
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                 Asm_GetNextFile);
+    return rv;
+  }
+
+  return NS_OK;
+}
+
 quota::Client* CreateClient() { return new Client(); }
 
 }  // namespace asmjscache
 }  // namespace dom
 }  // namespace mozilla
 
 namespace IPC {
 
--- a/dom/cache/QuotaClient.cpp
+++ b/dom/cache/QuotaClient.cpp
@@ -4,19 +4,21 @@
  * 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/. */
 
 #include "mozilla/dom/cache/QuotaClient.h"
 
 #include "DBAction.h"
 #include "FileUtils.h"
 #include "mozilla/dom/cache/Manager.h"
+#include "mozilla/dom/quota/QuotaCommon.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/UsageInfo.h"
 #include "mozilla/ipc/BackgroundParent.h"
+#include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "nsIFile.h"
 #include "nsISimpleEnumerator.h"
 #include "nsThreadUtils.h"
 
 namespace {
 
 using mozilla::Atomic;
@@ -146,128 +148,29 @@ class CacheQuotaClient final : public Cl
     AssertIsOnIOThread();
 
     // The QuotaManager passes a nullptr UsageInfo if there is no quota being
     // enforced against the origin.
     if (!aUsageInfo) {
       return NS_OK;
     }
 
-    return GetUsageForOrigin(aPersistenceType, aGroup, aOrigin, aCanceled,
-                             aUsageInfo);
+    return GetUsageForOriginInternal(aPersistenceType, aGroup, aOrigin,
+                                     aCanceled, aUsageInfo,
+                                     /* aInitializing*/ true);
   }
 
   virtual nsresult GetUsageForOrigin(PersistenceType aPersistenceType,
                                      const nsACString& aGroup,
                                      const nsACString& aOrigin,
                                      const AtomicBool& aCanceled,
                                      UsageInfo* aUsageInfo) override {
-    AssertIsOnIOThread();
-    MOZ_DIAGNOSTIC_ASSERT(aUsageInfo);
-
-    QuotaManager* qm = QuotaManager::Get();
-    MOZ_DIAGNOSTIC_ASSERT(qm);
-
-    nsCOMPtr<nsIFile> dir;
-    nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin,
-                                            getter_AddRefs(dir));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    rv = dir->Append(NS_LITERAL_STRING(DOMCACHE_DIRECTORY_NAME));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    int64_t paddingSize = 0;
-    {
-      // If the tempoary file still exists after locking, it means the previous
-      // action fails, so restore the padding file.
-      MutexAutoLock lock(mDirPaddingFileMutex);
-
-      if (mozilla::dom::cache::DirectoryPaddingFileExists(
-              dir, DirPaddingFile::TMP_FILE) ||
-          NS_WARN_IF(NS_FAILED(mozilla::dom::cache::LockedDirectoryPaddingGet(
-              dir, &paddingSize)))) {
-        rv = LockedGetPaddingSizeFromDB(dir, aGroup, aOrigin, &paddingSize);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
-        }
-      }
-    }
-
-    aUsageInfo->AppendToFileUsage(paddingSize);
-
-    nsCOMPtr<nsIDirectoryEnumerator> entries;
-    rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    nsCOMPtr<nsIFile> file;
-    while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(file))) &&
-           file && !aCanceled) {
-      nsAutoString leafName;
-      rv = file->GetLeafName(leafName);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-
-      bool isDir;
-      rv = file->IsDirectory(&isDir);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-
-      if (isDir) {
-        if (leafName.EqualsLiteral("morgue")) {
-          rv = GetBodyUsage(file, aCanceled, aUsageInfo);
-          if (NS_WARN_IF(NS_FAILED(rv))) {
-            return rv;
-          }
-        } else {
-          NS_WARNING("Unknown Cache directory found!");
-        }
-
-        continue;
-      }
-
-      // Ignore transient sqlite files and marker files
-      if (leafName.EqualsLiteral("caches.sqlite-journal") ||
-          leafName.EqualsLiteral("caches.sqlite-shm") ||
-          leafName.Find(NS_LITERAL_CSTRING("caches.sqlite-mj"), false, 0, 0) ==
-              0 ||
-          leafName.EqualsLiteral("context_open.marker")) {
-        continue;
-      }
-
-      if (leafName.EqualsLiteral("caches.sqlite") ||
-          leafName.EqualsLiteral("caches.sqlite-wal")) {
-        int64_t fileSize;
-        rv = file->GetFileSize(&fileSize);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
-        }
-        MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
-
-        aUsageInfo->AppendToDatabaseUsage(fileSize);
-        continue;
-      }
-
-      // Ignore directory padding file
-      if (leafName.EqualsLiteral(PADDING_FILE_NAME) ||
-          leafName.EqualsLiteral(PADDING_TMP_FILE_NAME)) {
-        continue;
-      }
-
-      NS_WARNING("Unknown Cache file found!");
-    }
-
-    return NS_OK;
+    return GetUsageForOriginInternal(aPersistenceType, aGroup, aOrigin,
+                                     aCanceled, aUsageInfo,
+                                     /* aInitializing*/ false);
   }
 
   virtual void OnOriginClearCompleted(PersistenceType aPersistenceType,
                                       const nsACString& aOrigin) override {
     // Nothing to do here.
   }
 
   virtual void ReleaseIOThreadObjects() override {
@@ -455,16 +358,145 @@ class CacheQuotaClient final : public Cl
  private:
   ~CacheQuotaClient() {
     AssertIsOnBackgroundThread();
     MOZ_DIAGNOSTIC_ASSERT(sInstance == this);
 
     sInstance = nullptr;
   }
 
+  nsresult GetUsageForOriginInternal(PersistenceType aPersistenceType,
+                                     const nsACString& aGroup,
+                                     const nsACString& aOrigin,
+                                     const AtomicBool& aCanceled,
+                                     UsageInfo* aUsageInfo,
+                                     const bool aInitializing) {
+    AssertIsOnIOThread();
+    MOZ_DIAGNOSTIC_ASSERT(aUsageInfo);
+#ifndef NIGHTLY_BUILD
+    Unused << aInitializing;
+#endif
+
+    QuotaManager* qm = QuotaManager::Get();
+    MOZ_DIAGNOSTIC_ASSERT(qm);
+
+    nsCOMPtr<nsIFile> dir;
+    nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin,
+                                            getter_AddRefs(dir));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                   Cache_GetDirForOri);
+      return rv;
+    }
+
+    rv = dir->Append(NS_LITERAL_STRING(DOMCACHE_DIRECTORY_NAME));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError, Cache_Append);
+      return rv;
+    }
+
+    int64_t paddingSize = 0;
+    {
+      // If the tempoary file still exists after locking, it means the previous
+      // action fails, so restore the padding file.
+      MutexAutoLock lock(mDirPaddingFileMutex);
+
+      if (mozilla::dom::cache::DirectoryPaddingFileExists(
+              dir, DirPaddingFile::TMP_FILE) ||
+          NS_WARN_IF(NS_FAILED(mozilla::dom::cache::LockedDirectoryPaddingGet(
+              dir, &paddingSize)))) {
+        rv = LockedGetPaddingSizeFromDB(dir, aGroup, aOrigin, &paddingSize);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kInternalError,
+                                       Cache_GetPaddingSize);
+          return rv;
+        }
+      }
+    }
+
+    aUsageInfo->AppendToFileUsage(paddingSize);
+
+    nsCOMPtr<nsIDirectoryEnumerator> entries;
+    rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                   Cache_GetDirEntries);
+      return rv;
+    }
+
+    nsCOMPtr<nsIFile> file;
+    while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(file))) &&
+           file && !aCanceled) {
+      nsAutoString leafName;
+      rv = file->GetLeafName(leafName);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                     Cache_GetLeafName);
+        return rv;
+      }
+
+      bool isDir;
+      rv = file->IsDirectory(&isDir);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                     Cache_IsDirectory);
+        return rv;
+      }
+
+      if (isDir) {
+        if (leafName.EqualsLiteral("morgue")) {
+          rv = GetBodyUsage(file, aCanceled, aUsageInfo);
+          if (NS_WARN_IF(NS_FAILED(rv))) {
+            REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                         Cache_GetBodyUsage);
+            return rv;
+          }
+        } else {
+          NS_WARNING("Unknown Cache directory found!");
+        }
+
+        continue;
+      }
+
+      // Ignore transient sqlite files and marker files
+      if (leafName.EqualsLiteral("caches.sqlite-journal") ||
+          leafName.EqualsLiteral("caches.sqlite-shm") ||
+          leafName.Find(NS_LITERAL_CSTRING("caches.sqlite-mj"), false, 0, 0) ==
+              0 ||
+          leafName.EqualsLiteral("context_open.marker")) {
+        continue;
+      }
+
+      if (leafName.EqualsLiteral("caches.sqlite") ||
+          leafName.EqualsLiteral("caches.sqlite-wal")) {
+        int64_t fileSize;
+        rv = file->GetFileSize(&fileSize);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kExternalError,
+                                       Cache_GetFileSize);
+          return rv;
+        }
+        MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
+
+        aUsageInfo->AppendToDatabaseUsage(fileSize);
+        continue;
+      }
+
+      // Ignore directory padding file
+      if (leafName.EqualsLiteral(PADDING_FILE_NAME) ||
+          leafName.EqualsLiteral(PADDING_TMP_FILE_NAME)) {
+        continue;
+      }
+
+      NS_WARNING("Unknown Cache file found!");
+    }
+
+    return NS_OK;
+  }
+
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheQuotaClient, override)
 
   // Mutex lock to protect directroy padding files. It should only be acquired
   // in DOM Cache IO threads and Quota IO thread.
   mozilla::Mutex mDirPaddingFileMutex;
 };
 
 // static
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -53,16 +53,17 @@
 #include "mozilla/dom/indexedDB/PBackgroundIDBVersionChangeTransactionParent.h"
 #include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsParent.h"
 #include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestParent.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
 #include "mozilla/dom/quota/Client.h"
 #include "mozilla/dom/quota/FileStreams.h"
 #include "mozilla/dom/quota/OriginScope.h"
+#include "mozilla/dom/quota/QuotaCommon.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/UsageInfo.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/InputStreamParams.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/PBackground.h"
 #include "mozilla/ipc/PBackgroundParent.h"
@@ -15513,125 +15514,139 @@ nsresult QuotaClient::InitOrigin(Persist
                                  const AtomicBool& aCanceled,
                                  UsageInfo* aUsageInfo) {
   AssertIsOnIOThread();
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv =
       GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_GetDirectory);
     return rv;
   }
 
   // We need to see if there are any files in the directory already. If they
   // are database files then we need to cleanup stored files (if it's needed)
   // and also get the usage.
 
   AutoTArray<nsString, 20> subdirsToProcess;
   nsTHashtable<nsStringHashKey> databaseFilenames(20);
   rv = GetDatabaseFilenames(directory, aCanceled,
                             /* aForUpgrade */ false, subdirsToProcess,
                             databaseFilenames);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_GetDBFilenames);
     return rv;
   }
 
   const NS_ConvertASCIItoUTF16 filesSuffix(
       kFileManagerDirectoryNameSuffix,
       LiteralStringLength(kFileManagerDirectoryNameSuffix));
 
   for (uint32_t count = subdirsToProcess.Length(), i = 0; i < count; i++) {
     const nsString& subdirName = subdirsToProcess[i];
 
     // The directory must have the correct suffix.
     nsDependentSubstring subdirNameBase;
     if (NS_WARN_IF(!GetBaseFilename(subdirName, filesSuffix, subdirNameBase))) {
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, IDB_GetBaseFilename);
       return NS_ERROR_UNEXPECTED;
     }
 
     // The directory base must exist in databaseFilenames.
     if (NS_WARN_IF(!databaseFilenames.GetEntry(subdirNameBase))) {
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, IDB_GetEntry);
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   const NS_ConvertASCIItoUTF16 sqliteSuffix(kSQLiteSuffix,
                                             LiteralStringLength(kSQLiteSuffix));
   const NS_ConvertASCIItoUTF16 walSuffix(kSQLiteWALSuffix,
                                          LiteralStringLength(kSQLiteWALSuffix));
 
   for (auto iter = databaseFilenames.ConstIter(); !iter.Done() && !aCanceled;
        iter.Next()) {
     auto& databaseFilename = iter.Get()->GetKey();
 
     nsCOMPtr<nsIFile> fmDirectory;
     rv = directory->Clone(getter_AddRefs(fmDirectory));
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_Clone);
       return rv;
     }
 
     rv = fmDirectory->Append(databaseFilename + filesSuffix);
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_Append);
       return rv;
     }
 
     nsCOMPtr<nsIFile> databaseFile;
     rv = directory->Clone(getter_AddRefs(databaseFile));
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_Clone2);
       return rv;
     }
 
     rv = databaseFile->Append(databaseFilename + sqliteSuffix);
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_Append2);
       return rv;
     }
 
     nsCOMPtr<nsIFile> walFile;
     if (aUsageInfo) {
       rv = directory->Clone(getter_AddRefs(walFile));
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_Clone3);
         return rv;
       }
 
       rv = walFile->Append(databaseFilename + walSuffix);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_Append3);
         return rv;
       }
     }
 
     rv = FileManager::InitDirectory(fmDirectory, databaseFile, aPersistenceType,
                                     aGroup, aOrigin,
                                     TelemetryIdForFile(databaseFile));
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, IDB_InitDirectory);
       return rv;
     }
 
     if (aUsageInfo) {
       int64_t fileSize;
       rv = databaseFile->GetFileSize(&fileSize);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_GetFileSize);
         return rv;
       }
 
       MOZ_ASSERT(fileSize >= 0);
 
       aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
 
       rv = walFile->GetFileSize(&fileSize);
       if (NS_SUCCEEDED(rv)) {
         MOZ_ASSERT(fileSize >= 0);
         aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
       } else if (NS_WARN_IF(rv != NS_ERROR_FILE_NOT_FOUND &&
                             rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_GetWalFileSize);
         return rv;
       }
 
       uint64_t usage;
       rv = FileManager::GetUsage(fmDirectory, &usage);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, IDB_GetUsage);
         return rv;
       }
 
       aUsageInfo->AppendToFileUsage(usage);
     }
   }
 
   return NS_OK;
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -9,27 +9,29 @@
 #include "LocalStorageCommon.h"
 #include "LSObject.h"
 #include "mozIStorageConnection.h"
 #include "mozIStorageFunction.h"
 #include "mozIStorageService.h"
 #include "mozStorageCID.h"
 #include "mozStorageHelper.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/PBackgroundLSDatabaseParent.h"
 #include "mozilla/dom/PBackgroundLSObserverParent.h"
 #include "mozilla/dom/PBackgroundLSRequestParent.h"
 #include "mozilla/dom/PBackgroundLSSharedTypes.h"
 #include "mozilla/dom/PBackgroundLSSimpleRequestParent.h"
 #include "mozilla/dom/PBackgroundLSSnapshotParent.h"
 #include "mozilla/dom/StorageDBUpdater.h"
 #include "mozilla/dom/StorageUtils.h"
 #include "mozilla/dom/quota/OriginScope.h"
+#include "mozilla/dom/quota/QuotaCommon.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/QuotaObject.h"
 #include "mozilla/dom/quota/UsageInfo.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/PBackgroundParent.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
@@ -7182,206 +7184,231 @@ nsresult QuotaClient::InitOrigin(Persist
 
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = quotaManager->GetDirectoryForOrigin(aPersistenceType, aOrigin,
                                                     getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_GetDirForOrigin);
     return rv;
   }
 
   MOZ_ASSERT(directory);
 
   rv = directory->Append(NS_LITERAL_STRING(LS_DIRECTORY_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_Append);
     return rv;
   }
 
 #ifdef DEBUG
   bool exists;
   rv = directory->Exists(&exists);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_Exists);
     return rv;
   }
 
   MOZ_ASSERT(exists);
 #endif
 
   nsString directoryPath;
   rv = directory->GetPath(directoryPath);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_GetPath);
     return rv;
   }
 
   nsCOMPtr<nsIFile> usageFile;
   rv = GetUsageFile(directoryPath, getter_AddRefs(usageFile));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_GetUsageFile);
     return rv;
   }
 
   bool usageFileExists;
 
   bool isDirectory;
   rv = usageFile->IsDirectory(&isDirectory);
   if (rv != NS_ERROR_FILE_NOT_FOUND &&
       rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_IsDirectory);
       return rv;
     }
 
     if (NS_WARN_IF(isDirectory)) {
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, LS_UnexpectedDir);
       return NS_ERROR_FAILURE;
     }
 
     usageFileExists = true;
   } else {
     usageFileExists = false;
   }
 
   nsCOMPtr<nsIFile> usageJournalFile;
   rv = GetUsageJournalFile(directoryPath, getter_AddRefs(usageJournalFile));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_GetUsageForJFile);
     return rv;
   }
 
   rv = usageJournalFile->IsDirectory(&isDirectory);
   if (rv != NS_ERROR_FILE_NOT_FOUND &&
       rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_IsDirectory2);
       return rv;
     }
 
     if (NS_WARN_IF(isDirectory)) {
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, LS_UnexpectedDir2);
       return NS_ERROR_FAILURE;
     }
 
     if (usageFileExists) {
       rv = usageFile->Remove(false);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_Remove);
         return rv;
       }
 
       usageFileExists = false;
     }
 
     rv = usageJournalFile->Remove(false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_Remove2);
       return rv;
     }
   }
 
   nsCOMPtr<nsIFile> file;
   rv = directory->Clone(getter_AddRefs(file));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_Clone);
     return rv;
   }
 
   rv = file->Append(NS_LITERAL_STRING(DATA_FILE_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_Append2);
     return rv;
   }
 
   rv = file->IsDirectory(&isDirectory);
   if (rv != NS_ERROR_FILE_NOT_FOUND &&
       rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_IsDirectory3);
       return rv;
     }
 
     if (NS_WARN_IF(isDirectory)) {
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, LS_UnexpectedDir3);
       return NS_ERROR_FAILURE;
     }
 
     int64_t usage;
     rv = LoadUsageFile(usageFile, &usage);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       nsCOMPtr<mozIStorageConnection> connection;
       bool dummy;
       rv = CreateStorageConnection(file, usageFile, aOrigin,
                                    getter_AddRefs(connection), &dummy);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_CreateConnection);
         return rv;
       }
 
       rv = GetUsage(connection, /* aArchivedOriginScope */ nullptr, &usage);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_GetUsage);
         return rv;
       }
 
       rv = UpdateUsageFile(usageFile, usageJournalFile, usage);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_UpdateUsageFile);
         return rv;
       }
 
       rv = usageJournalFile->Remove(false);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_Remove3);
         return rv;
       }
     }
 
     MOZ_ASSERT(usage >= 0);
 
     InitUsageForOrigin(aOrigin, usage);
 
     aUsageInfo->AppendToDatabaseUsage(uint64_t(usage));
   } else if (usageFileExists) {
     rv = usageFile->Remove(false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_Remove4);
       return rv;
     }
   }
 
   // Report unknown files in debug builds, but don't fail, just warn.
 
 #ifdef DEBUG
   nsCOMPtr<nsIDirectoryEnumerator> directoryEntries;
   rv = directory->GetDirectoryEntries(getter_AddRefs(directoryEntries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_GetDirEntries);
     return rv;
   }
 
   if (!directoryEntries) {
     return NS_OK;
   }
 
   while (true) {
     if (aCanceled) {
       break;
     }
 
     nsCOMPtr<nsIFile> file;
     rv = directoryEntries->GetNextFile(getter_AddRefs(file));
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_GetNextFile);
       return rv;
     }
 
     if (!file) {
       break;
     }
 
     nsString leafName;
     rv = file->GetLeafName(leafName);
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_GetLeafName);
       return rv;
     }
 
     // Don't need to check for USAGE_JOURNAL_FILE_NAME. We removed it above
     // (if there was any).
     if (leafName.EqualsLiteral(DATA_FILE_NAME) ||
         leafName.EqualsLiteral(USAGE_FILE_NAME)) {
       // Don't need to check if it is a directory or file. We did that above.
       continue;
     }
 
     if (leafName.EqualsLiteral(JOURNAL_FILE_NAME)) {
       bool isDirectory;
       rv = file->IsDirectory(&isDirectory);
       if (NS_WARN_IF(NS_FAILED(rv))) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, LS_IsDirectory4);
         return rv;
       }
 
       if (!isDirectory) {
         continue;
       }
     }
 
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -44,16 +44,17 @@
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/IntegerRange.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TextUtils.h"
+#include "mozilla/Telemetry.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Unused.h"
 #include "mozStorageCID.h"
 #include "mozStorageHelper.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsComponentManagerUtils.h"
 #include "nsAboutProtocolUtils.h"
 #include "nsCharSeparatedTokenizer.h"
@@ -3620,28 +3621,34 @@ nsresult QuotaManager::GetDirectoryMetad
   aGroup = group;
   aOrigin = origin;
   return NS_OK;
 }
 
 nsresult QuotaManager::GetDirectoryMetadata2WithRestore(
     nsIFile* aDirectory, bool aPersistent, int64_t* aTimestamp,
     bool* aPersisted, nsACString& aSuffix, nsACString& aGroup,
-    nsACString& aOrigin) {
+    nsACString& aOrigin, const bool aTelemetry) {
   nsresult rv = GetDirectoryMetadata2(aDirectory, aTimestamp, aPersisted,
                                       aSuffix, aGroup, aOrigin);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     rv = RestoreDirectoryMetadata2(aDirectory, aPersistent);
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      if (aTelemetry) {
+        REPORT_TELEMETRY_INIT_ERR(kInternalError, Rep_RestoreDirMeta);
+      }
       return rv;
     }
 
     rv = GetDirectoryMetadata2(aDirectory, aTimestamp, aPersisted, aSuffix,
                                aGroup, aOrigin);
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      if (aTelemetry) {
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, Rep_GetDirMeta);
+      }
       return rv;
     }
   }
 
   return NS_OK;
 }
 
 nsresult QuotaManager::GetDirectoryMetadata2(nsIFile* aDirectory,
@@ -3706,77 +3713,108 @@ nsresult QuotaManager::GetDirectoryMetad
 nsresult QuotaManager::InitializeRepository(PersistenceType aPersistenceType) {
   MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY ||
              aPersistenceType == PERSISTENCE_TYPE_DEFAULT);
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = NS_NewLocalFile(GetStoragePath(aPersistenceType), false,
                                 getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, Rep_NewLocalFile);
     return rv;
   }
 
   bool created;
   rv = EnsureDirectory(directory, &created);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, Rep_EnsureDirectory);
     return rv;
   }
 
   nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, Rep_GetDirEntries);
+    return rv;
+  }
+
+  // A keeper to defer the return only in Nightly, so that the telemetry data
+  // for whole profile can be collected
+#ifdef NIGHTLY_BUILD
+  nsresult statusKeeper = NS_OK;
+#endif
 
   nsCOMPtr<nsIFile> childDirectory;
   while (NS_SUCCEEDED(
              (rv = entries->GetNextFile(getter_AddRefs(childDirectory)))) &&
          childDirectory) {
     bool isDirectory;
     rv = childDirectory->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, Rep_IsDirectory);
+      RECORD_IN_NIGHTLY(statusKeeper, rv);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(rv);
     }
 
     if (!isDirectory) {
       nsString leafName;
       rv = childDirectory->GetLeafName(leafName);
       if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
+        REPORT_TELEMETRY_INIT_ERR(kExternalError, Rep_GetLeafName);
+        RECORD_IN_NIGHTLY(statusKeeper, rv);
+        CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(rv);
       }
 
       if (IsOSMetadata(leafName)) {
         continue;
       }
 
       UNKNOWN_FILE_WARNING(leafName);
-      return NS_ERROR_UNEXPECTED;
+
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, Rep_UnexpectedFile);
+      RECORD_IN_NIGHTLY(statusKeeper, NS_ERROR_UNEXPECTED);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(NS_ERROR_UNEXPECTED);
     }
 
     int64_t timestamp;
     bool persisted;
     nsCString suffix;
     nsCString group;
     nsCString origin;
     rv = GetDirectoryMetadata2WithRestore(childDirectory,
                                           /* aPersistent */ false, &timestamp,
-                                          &persisted, suffix, group, origin);
+                                          &persisted, suffix, group, origin,
+                                          /* aTelemetry */ true);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+      // Error should have reported in GetDirectoryMetadata2WithRestore
+      RECORD_IN_NIGHTLY(statusKeeper, rv);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(rv);
     }
 
     rv = InitializeOrigin(aPersistenceType, group, origin, timestamp, persisted,
                           childDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-  }
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
+      // Error should have reported in InitializeOrigin
+      RECORD_IN_NIGHTLY(statusKeeper, rv);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(rv);
+    }
+  }
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kInternalError, Rep_GetNextFile);
+    RECORD_IN_NIGHTLY(statusKeeper, rv);
+#ifndef NIGHTLY_BUILD
+    return rv;
+#endif
+  }
+
+#ifdef NIGHTLY_BUILD
+  if (NS_FAILED(statusKeeper)) {
+    return statusKeeper;
+  }
+#endif
 
   return NS_OK;
 }
 
 nsresult QuotaManager::InitializeOrigin(PersistenceType aPersistenceType,
                                         const nsACString& aGroup,
                                         const nsACString& aOrigin,
                                         int64_t aAccessTime, bool aPersisted,
@@ -3789,65 +3827,101 @@ nsresult QuotaManager::InitializeOrigin(
 
   // We need to initialize directories of all clients if they exists and also
   // get the total usage to initialize the quota.
   nsAutoPtr<UsageInfo> usageInfo;
   if (trackQuota) {
     usageInfo = new UsageInfo();
   }
 
+  // A keeper to defer the return only in Nightly, so that the telemetry data
+  // for whole profile can be collected
+#ifdef NIGHTLY_BUILD
+  nsresult statusKeeper = NS_OK;
+#endif
+
   nsCOMPtr<nsIDirectoryEnumerator> entries;
   rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kExternalError, Ori_GetDirEntries);
+    return rv;
+  }
 
   nsCOMPtr<nsIFile> file;
   while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
          file) {
     bool isDirectory;
     rv = file->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, Ori_IsDirectory);
+      RECORD_IN_NIGHTLY(statusKeeper, rv);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(rv);
     }
 
     nsString leafName;
     rv = file->GetLeafName(leafName);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+      REPORT_TELEMETRY_INIT_ERR(kExternalError, Ori_GetLeafName);
+      RECORD_IN_NIGHTLY(statusKeeper, rv);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(rv);
     }
 
     if (!isDirectory) {
       if (IsOriginMetadata(leafName)) {
         continue;
       }
 
       if (IsTempMetadata(leafName)) {
         rv = file->Remove(/* recursive */ false);
         if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
+          REPORT_TELEMETRY_INIT_ERR(kExternalError, Ori_Remove);
+          RECORD_IN_NIGHTLY(statusKeeper, rv);
+          CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(rv);
         }
 
         continue;
       }
 
       UNKNOWN_FILE_WARNING(leafName);
-      return NS_ERROR_UNEXPECTED;
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, Ori_UnexpectedFile);
+      RECORD_IN_NIGHTLY(statusKeeper, NS_ERROR_UNEXPECTED);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(NS_ERROR_UNEXPECTED);
     }
 
     Client::Type clientType;
     rv = Client::TypeFromText(leafName, clientType);
     if (NS_FAILED(rv)) {
       UNKNOWN_FILE_WARNING(leafName);
-      return NS_ERROR_UNEXPECTED;
+      REPORT_TELEMETRY_INIT_ERR(kInternalError, Ori_UnexpectedClient);
+      RECORD_IN_NIGHTLY(statusKeeper, NS_ERROR_UNEXPECTED);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(NS_ERROR_UNEXPECTED);
     }
 
     Atomic<bool> dummy(false);
     rv = mClients[clientType]->InitOrigin(aPersistenceType, aGroup, aOrigin,
                                           /* aCanceled */ dummy, usageInfo);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      // error should have reported in InitOrigin
+      RECORD_IN_NIGHTLY(statusKeeper, rv);
+      CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(rv);
+    }
+  }
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    REPORT_TELEMETRY_INIT_ERR(kInternalError, Ori_GetNextFile);
+    RECORD_IN_NIGHTLY(statusKeeper, rv);
+#ifndef NIGHTLY_BUILD
+    return rv;
+#endif
+  }
+
+#ifdef NIGHTLY_BUILD
+  if (NS_FAILED(statusKeeper)) {
+    return statusKeeper;
+  }
+#endif
 
   if (trackQuota) {
     InitQuotaForOrigin(aPersistenceType, aGroup, aOrigin,
                        usageInfo->TotalUsage(), aAccessTime, aPersisted);
   }
 
   return NS_OK;
 }
@@ -5007,30 +5081,42 @@ nsresult QuotaManager::EnsureTemporarySt
   MOZ_ASSERT(mStorageInitialized);
 
   if (mTemporaryStorageInitialized) {
     return NS_OK;
   }
 
   TimeStamp startTime = TimeStamp::Now();
 
+  // A keeper to defer the return only in Nightly, so that the telemetry data
+  // for whole profile can be collected
+  nsresult statusKeeper = NS_OK;
+
   nsresult rv = InitializeRepository(PERSISTENCE_TYPE_DEFAULT);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    RECORD_IN_NIGHTLY(statusKeeper, rv);
+
+#ifndef NIGHTLY_BUILD
     // We have to cleanup partially initialized quota.
     RemoveQuota();
 
     return rv;
+#endif
   }
 
   rv = InitializeRepository(PERSISTENCE_TYPE_TEMPORARY);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
+  if (NS_WARN_IF(NS_FAILED(rv)) || NS_FAILED(statusKeeper)) {
     // We have to cleanup partially initialized quota.
     RemoveQuota();
 
-    return rv;
+#ifdef NIGHTLY_BUILD
+    return NS_FAILED(statusKeeper) ? statusKeeper : rv;
+#else
+    return rv;
+#endif
   }
 
   Telemetry::AccumulateTimeDelta(Telemetry::QM_REPOSITORIES_INITIALIZATION_TIME,
                                  startTime, TimeStamp::Now());
 
   if (gFixedLimitKB >= 0) {
     mTemporaryStorageLimit = static_cast<uint64_t>(gFixedLimitKB) * 1024;
   } else {
--- a/dom/quota/QuotaCommon.h
+++ b/dom/quota/QuotaCommon.h
@@ -27,20 +27,64 @@
 
 #define QM_WARNING(...)                                                      \
   do {                                                                       \
     nsPrintfCString str(__VA_ARGS__);                                        \
     mozilla::dom::quota::ReportInternalError(__FILE__, __LINE__, str.get()); \
     NS_WARNING(str.get());                                                   \
   } while (0)
 
+// Telemetry probes to collect number of failure during the initialization.
+#ifdef NIGHTLY_BUILD
+#define REPORT_TELEMETRY_INIT_ERR(_key, _label)   \
+  mozilla::Telemetry::AccumulateCategoricalKeyed( \
+      mozilla::dom::quota::_key,                  \
+      mozilla::Telemetry::LABELS_QM_INIT_TELEMETRY_ERROR::_label);
+
+#define REPORT_TELEMETRY_ERR_IN_INIT(_initializing, _key, _label) \
+  do {                                                            \
+    if (_initializing) {                                          \
+      REPORT_TELEMETRY_INIT_ERR(_key, _label)                     \
+    }                                                             \
+  } while (0)
+
+#define RECORD_IN_NIGHTLY(_recorder, _status) \
+  do {                                        \
+    if (NS_SUCCEEDED(_recorder)) {            \
+      _recorder = _status;                    \
+    }                                         \
+  } while (0)
+
+#define CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(_dummy) continue
+#else
+#define REPORT_TELEMETRY_INIT_ERR(_key, _label) \
+  {}
+
+#define REPORT_TELEMETRY_ERR_IN_INIT(_initializing, _key, _label) \
+  {}
+
+#define RECORD_IN_NIGHTLY(_dummy, _status) \
+  {}
+
+#define CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(_rv) return _rv
+#endif
+
 class nsIEventTarget;
 
 BEGIN_QUOTA_NAMESPACE
 
+// Telemetry keys to indicate types of errors.
+#ifdef NIGHTLY_BUILD
+const nsCString kInternalError = NS_LITERAL_CSTRING("internal");
+const nsCString kExternalError = NS_LITERAL_CSTRING("external");
+#else
+const nsCString kInternalError = EmptyCString();
+const nsCString kExternalError = EmptyCString();
+#endif
+
 class BackgroundThreadObject {
  protected:
   nsCOMPtr<nsIEventTarget> mOwningThread;
 
  public:
   void AssertIsOnOwningThread() const
 #ifdef DEBUG
       ;
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -180,17 +180,17 @@ class QuotaManager final : public Backgr
 
   nsresult GetDirectoryMetadata2(nsIFile* aDirectory, int64_t* aTimestamp,
                                  bool* aPersisted, nsACString& aSuffix,
                                  nsACString& aGroup, nsACString& aOrigin);
 
   nsresult GetDirectoryMetadata2WithRestore(
       nsIFile* aDirectory, bool aPersistent, int64_t* aTimestamp,
       bool* aPersisted, nsACString& aSuffix, nsACString& aGroup,
-      nsACString& aOrigin);
+      nsACString& aOrigin, const bool aTelemetry = false);
 
   nsresult GetDirectoryMetadata2(nsIFile* aDirectory, int64_t* aTimestamp,
                                  bool* aPersisted);
 
   nsresult GetDirectoryMetadata2WithRestore(nsIFile* aDirectory,
                                             bool aPersistent,
                                             int64_t* aTimestamp,
                                             bool* aPersisted);
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -14553,10 +14553,90 @@
     ],
     "expires_in_version": "70",
     "kind": "exponential",
     "low": 1,
     "high": 500,
     "n_buckets": 50,
     "bug_numbers": [1518624],
     "description": "The amount of scroll adjustments performed by scroll anchoring in a top-level document."
+  },
+  "QM_INIT_TELEMETRY_ERROR": {
+      "record_in_processes": ["main"],
+      "alert_emails": ["ttung@mozilla.com"],
+      "expires_in_version": "70",
+      "bug_numbers": [1436188],
+      "kind": "categorical",
+      "n_values": 75,
+      "labels": [
+          "Rep_NewLocalFile",
+          "Rep_EnsureDirectory",
+          "Rep_GetDirEntries",
+          "Rep_IsDirectory",
+          "Rep_GetLeafName",
+          "Rep_UnexpectedFile",
+          "Rep_GetNextFile",
+          "Rep_RestoreDirMeta",
+          "Rep_GetDirMeta",
+          "Ori_GetDirEntries",
+          "Ori_IsDirectory",
+          "Ori_GetLeafName",
+          "Ori_Remove",
+          "Ori_UnexpectedFile",
+          "Ori_UnexpectedClient",
+          "Ori_GetNextFile",
+          "Asm_GetDirForOrigin",
+          "Asm_Append",
+          "Asm_GetDirEntries",
+          "Asm_GetFileSize",
+          "Asm_GetNextFile",
+          "Cache_GetDirForOri",
+          "Cache_Append",
+          "Cache_GetPaddingSize",
+          "Cache_GetDirEntries",
+          "Cache_GetLeafName",
+          "Cache_IsDirectory",
+          "Cache_GetBodyUsage",
+          "Cache_GetFileSize",
+          "LS_GetDirForOrigin",
+          "LS_Append",
+          "LS_Exists",
+          "LS_GetPath",
+          "LS_GetUsageFile",
+          "LS_IsDirectory",
+          "LS_UnexpectedDir",
+          "LS_GetUsageForJFile",
+          "LS_IsDirectory2",
+          "LS_UnexpectedDir2",
+          "LS_Remove",
+          "LS_Remove2",
+          "LS_Clone",
+          "LS_Append2",
+          "LS_IsDirectory3",
+          "LS_UnexpectedDir3",
+          "LS_CreateConnection",
+          "LS_GetUsage",
+          "LS_UpdateUsageFile",
+          "LS_Remove3",
+          "LS_Remove4",
+          "LS_GetDirEntries",
+          "LS_GetNextFile",
+          "LS_GetLeafName",
+          "LS_IsDirectory4",
+          "IDB_GetDirectory",
+          "IDB_GetDBFilenames",
+          "IDB_GetBaseFilename",
+          "IDB_GetEntry",
+          "IDB_Clone",
+          "IDB_Append",
+          "IDB_Clone2",
+          "IDB_Append2",
+          "IDB_Clone3",
+          "IDB_Append3",
+          "IDB_InitDirectory",
+          "IDB_GetFileSize",
+          "IDB_GetWalFileSize",
+          "IDB_GetUsage"
+      ],
+      "keyed": true,
+      "description": "Getting the number of errors in QuotaManager initialization."
   }
 }