diff options
Diffstat (limited to 'toolkit/components/telemetry/geckoview/streaming/GeckoViewStreamingTelemetry.cpp')
-rw-r--r-- | toolkit/components/telemetry/geckoview/streaming/GeckoViewStreamingTelemetry.cpp | 282 |
1 files changed, 0 insertions, 282 deletions
diff --git a/toolkit/components/telemetry/geckoview/streaming/GeckoViewStreamingTelemetry.cpp b/toolkit/components/telemetry/geckoview/streaming/GeckoViewStreamingTelemetry.cpp deleted file mode 100644 index 6c4b9590c0..0000000000 --- a/toolkit/components/telemetry/geckoview/streaming/GeckoViewStreamingTelemetry.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#include "GeckoViewStreamingTelemetry.h" - -#include "mozilla/Assertions.h" -#include "mozilla/Services.h" -#include "mozilla/StaticMutex.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/StaticPrefs_toolkit.h" -#include "mozilla/TimeStamp.h" -#include "nsTHashMap.h" -#include "nsIObserver.h" -#include "nsIObserverService.h" -#include "nsITimer.h" -#include "nsTArray.h" -#include "nsThreadUtils.h" - -using mozilla::Runnable; -using mozilla::StaticMutex; -using mozilla::StaticMutexAutoLock; -using mozilla::StaticRefPtr; -using mozilla::TimeStamp; - -// Batches and streams Telemetry samples to a JNI delegate which will -// (presumably) do something with the data. Expected to be used to route data -// up to the Android Components layer to be translated into Glean metrics. -namespace GeckoViewStreamingTelemetry { - -class LifecycleObserver; -void SendBatch(const StaticMutexAutoLock& aLock); - -// Topic on which we flush the batch. -static const char* const kApplicationBackgroundTopic = "application-background"; - -static StaticMutex gMutex MOZ_UNANNOTATED; - -// -- The following state is accessed across threads. -// -- Do not touch these if you do not hold gMutex. - -// The time the batch began. -TimeStamp gBatchBegan; -// The batch of histograms and samples. -typedef nsTHashMap<nsCStringHashKey, nsTArray<uint32_t>> HistogramBatch; -HistogramBatch gBatch; -HistogramBatch gCategoricalBatch; -// The batches of Scalars and their values. -typedef nsTHashMap<nsCStringHashKey, bool> BoolScalarBatch; -BoolScalarBatch gBoolScalars; -typedef nsTHashMap<nsCStringHashKey, nsCString> StringScalarBatch; -StringScalarBatch gStringScalars; -typedef nsTHashMap<nsCStringHashKey, uint32_t> UintScalarBatch; -UintScalarBatch gUintScalars; -// The delegate to receive the samples and values. -StaticRefPtr<StreamingTelemetryDelegate> gDelegate; -// Lifecycle observer used to flush the batch when backgrounded. -StaticRefPtr<LifecycleObserver> gObserver; - -// -- End of gMutex-protected thread-unsafe-accessed data - -// Timer that ensures data in the batch never gets too stale. -// This timer may only be manipulated on the Main Thread. -StaticRefPtr<nsITimer> gJICTimer; - -class LifecycleObserver final : public nsIObserver { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - - LifecycleObserver() = default; - - protected: - ~LifecycleObserver() = default; -}; - -NS_IMPL_ISUPPORTS(LifecycleObserver, nsIObserver); - -NS_IMETHODIMP -LifecycleObserver::Observe(nsISupports* aSubject, const char* aTopic, - const char16_t* aData) { - if (!strcmp(aTopic, kApplicationBackgroundTopic)) { - StaticMutexAutoLock lock(gMutex); - SendBatch(lock); - } - return NS_OK; -} - -void RegisterDelegate(const RefPtr<StreamingTelemetryDelegate>& aDelegate) { - StaticMutexAutoLock lock(gMutex); - gDelegate = aDelegate; -} - -class SendBatchRunnable : public Runnable { - public: - explicit SendBatchRunnable(RefPtr<StreamingTelemetryDelegate> aDelegate, - HistogramBatch&& aBatch, - HistogramBatch&& aCategoricalBatch, - BoolScalarBatch&& aBoolScalars, - StringScalarBatch&& aStringScalars, - UintScalarBatch&& aUintScalars) - : Runnable("SendBatchRunnable"), - mDelegate(std::move(aDelegate)), - mBatch(std::move(aBatch)), - mCategoricalBatch(std::move(aCategoricalBatch)), - mBoolScalars(std::move(aBoolScalars)), - mStringScalars(std::move(aStringScalars)), - mUintScalars(std::move(aUintScalars)) {} - - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mDelegate); - - if (gJICTimer) { - gJICTimer->Cancel(); - } - - for (const auto& entry : mBatch) { - const nsCString& histogramName = PromiseFlatCString(entry.GetKey()); - const nsTArray<uint32_t>& samples = entry.GetData(); - - mDelegate->ReceiveHistogramSamples(histogramName, samples); - } - mBatch.Clear(); - - for (const auto& entry : mCategoricalBatch) { - const nsCString& histogramName = PromiseFlatCString(entry.GetKey()); - const nsTArray<uint32_t>& samples = entry.GetData(); - - mDelegate->ReceiveCategoricalHistogramSamples(histogramName, samples); - } - mCategoricalBatch.Clear(); - - for (const auto& entry : mBoolScalars) { - const nsCString& scalarName = PromiseFlatCString(entry.GetKey()); - mDelegate->ReceiveBoolScalarValue(scalarName, entry.GetData()); - } - mBoolScalars.Clear(); - - for (const auto& entry : mStringScalars) { - const nsCString& scalarName = PromiseFlatCString(entry.GetKey()); - const nsCString& scalarValue = PromiseFlatCString(entry.GetData()); - mDelegate->ReceiveStringScalarValue(scalarName, scalarValue); - } - mStringScalars.Clear(); - - for (const auto& entry : mUintScalars) { - const nsCString& scalarName = PromiseFlatCString(entry.GetKey()); - mDelegate->ReceiveUintScalarValue(scalarName, entry.GetData()); - } - mUintScalars.Clear(); - - return NS_OK; - } - - private: - RefPtr<StreamingTelemetryDelegate> mDelegate; - HistogramBatch mBatch; - HistogramBatch mCategoricalBatch; - BoolScalarBatch mBoolScalars; - StringScalarBatch mStringScalars; - UintScalarBatch mUintScalars; -}; // class SendBatchRunnable - -// Can be called on any thread. -// NOTE: Pay special attention to what you call in this method as if it -// accumulates to a gv-streaming-enabled probe we will deadlock the calling -// thread. -void SendBatch(const StaticMutexAutoLock& aLock) { - if (!gDelegate) { - NS_WARNING( - "Being asked to send Streaming Telemetry with no registered Streaming " - "Telemetry Delegate. Will try again later."); - // Give us another full Batch Duration to register a delegate. - gBatchBegan = TimeStamp::Now(); - return; - } - - // To make it so accumulations within the delegation don't deadlock us, - // move the batches' contents into the Runner. - HistogramBatch histogramCopy; - gBatch.SwapElements(histogramCopy); - HistogramBatch categoricalCopy; - gCategoricalBatch.SwapElements(categoricalCopy); - BoolScalarBatch boolScalarCopy; - gBoolScalars.SwapElements(boolScalarCopy); - StringScalarBatch stringScalarCopy; - gStringScalars.SwapElements(stringScalarCopy); - UintScalarBatch uintScalarCopy; - gUintScalars.SwapElements(uintScalarCopy); - RefPtr<SendBatchRunnable> runnable = new SendBatchRunnable( - gDelegate, std::move(histogramCopy), std::move(categoricalCopy), - std::move(boolScalarCopy), std::move(stringScalarCopy), - std::move(uintScalarCopy)); - - // To make things easier for the delegate, dispatch to the main thread. - NS_DispatchToMainThread(runnable); -} - -// Can be called on any thread. -void BatchCheck(const StaticMutexAutoLock& aLock) { - if (!gObserver) { - gObserver = new LifecycleObserver(); - nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); - if (os) { - os->AddObserver(gObserver, kApplicationBackgroundTopic, false); - } - } - if (gBatchBegan.IsNull()) { - // Time to begin a new batch. - gBatchBegan = TimeStamp::Now(); - // Set a just-in-case timer to enforce an upper-bound on batch staleness. - NS_DispatchToMainThread(NS_NewRunnableFunction( - "GeckoviewStreamingTelemetry::ArmTimer", []() -> void { - if (!gJICTimer) { - gJICTimer = NS_NewTimer().take(); - } - if (gJICTimer) { - gJICTimer->InitWithNamedFuncCallback( - [](nsITimer*, void*) -> void { - StaticMutexAutoLock locker(gMutex); - SendBatch(locker); - }, - nullptr, - mozilla::StaticPrefs:: - toolkit_telemetry_geckoview_maxBatchStalenessMS(), - nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY, - "GeckoviewStreamingTelemetry::SendBatch"); - } - })); - } - double batchDurationMs = (TimeStamp::Now() - gBatchBegan).ToMilliseconds(); - if (batchDurationMs > - mozilla::StaticPrefs::toolkit_telemetry_geckoview_batchDurationMS()) { - SendBatch(aLock); - gBatchBegan = TimeStamp(); - } -} - -// Can be called on any thread. -void HistogramAccumulate(const nsCString& aName, bool aIsCategorical, - uint32_t aValue) { - StaticMutexAutoLock lock(gMutex); - - if (aIsCategorical) { - nsTArray<uint32_t>& samples = gCategoricalBatch.LookupOrInsert(aName); - samples.AppendElement(aValue); - } else { - nsTArray<uint32_t>& samples = gBatch.LookupOrInsert(aName); - samples.AppendElement(aValue); - } - - BatchCheck(lock); -} - -void BoolScalarSet(const nsCString& aName, bool aValue) { - StaticMutexAutoLock lock(gMutex); - - gBoolScalars.InsertOrUpdate(aName, aValue); - - BatchCheck(lock); -} - -void StringScalarSet(const nsCString& aName, const nsCString& aValue) { - StaticMutexAutoLock lock(gMutex); - - gStringScalars.InsertOrUpdate(aName, aValue); - - BatchCheck(lock); -} - -void UintScalarSet(const nsCString& aName, uint32_t aValue) { - StaticMutexAutoLock lock(gMutex); - - gUintScalars.InsertOrUpdate(aName, aValue); - - BatchCheck(lock); -} - -} // namespace GeckoViewStreamingTelemetry |