diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 45deac468a35..ba9bf096fcfd 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -9530,6 +9530,32 @@ "releaseChannelCollection": "opt-out", "description": "A counter incremented every time the user prints a document." }, + "PRINT_BACKGROUND_TASK_TIME_MS" : { + "record_in_processes": ["main"], + "products": ["firefox"], + "alert_emails": ["jwatt@jwatt.org"], + "expires_in_version": "88", + "description": "Milliseconds taken on the background thread only for print background tasks. Keys describe the task, usually the information being retrieved, current possible keys are: DefaultSettings, MarginsForPaper, Printers, NamedPrinter, NamedOrDefaultPrinter, SupportsDuplex, SupportsColor, SupportsCollation, PaperList.", + "keyed": true, + "kind": "exponential", + "high": 10000, + "n_buckets": 50, + "releaseChannelCollection": "opt-out", + "bug_numbers": [1660686] + }, + "PRINT_BACKGROUND_TASK_ROUND_TRIP_TIME_MS" : { + "record_in_processes": ["main"], + "products": ["firefox"], + "alert_emails": ["jwatt@jwatt.org"], + "expires_in_version": "88", + "description": "Milliseconds taken for print background tasks from spawning to background thread back to before resolving or rejecting on the main thread. See PRINT_BACKGROUND_TASK_TIME_MS for key description.", + "keyed": true, + "kind": "exponential", + "high": 10000, + "n_buckets": 50, + "releaseChannelCollection": "opt-out", + "bug_numbers": [1660686] + }, "DEVTOOLS_COLD_TOOLBOX_OPEN_DELAY_MS": { "record_in_processes": ["main"], "products": ["firefox", "fennec"], diff --git a/widget/PrintBackgroundTask.h b/widget/PrintBackgroundTask.h index 7d938a2b221c..d8b4d8a4e58f 100644 --- a/widget/PrintBackgroundTask.h +++ b/widget/PrintBackgroundTask.h @@ -8,6 +8,7 @@ #include "mozilla/dom/Promise.h" #include "mozilla/ErrorResult.h" +#include "mozilla/Telemetry.h" #include #include @@ -28,7 +29,7 @@ using PrintBackgroundTask = Result (T::*)(Args...) const; template void SpawnPrintBackgroundTask( - T& aReceiver, dom::Promise& aPromise, + T& aReceiver, dom::Promise& aPromise, const nsCString& aTelemetryKey, PrintBackgroundTask aBackgroundTask, Args... aArgs) { auto promiseHolder = MakeRefPtr>( "nsPrinterBase::SpawnBackgroundTaskPromise", &aPromise); @@ -45,18 +46,26 @@ void SpawnPrintBackgroundTask( NS_NewRunnableFunction( "SpawnPrintBackgroundTask", [holder = std::move(holder), promiseHolder = std::move(promiseHolder), - aBackgroundTask, + aTelemetryKey, startRoundTrip = TimeStamp::Now(), + backgroundTask = aBackgroundTask, aArgs = std::make_tuple(std::forward(aArgs)...)] { + auto start = TimeStamp::Now(); Result result = std::apply( [&](auto&&... args) { - return (holder->get()->*aBackgroundTask)(args...); + return (holder->get()->*backgroundTask)(args...); }, std::move(aArgs)); + Telemetry::AccumulateTimeDelta( + Telemetry::PRINT_BACKGROUND_TASK_TIME_MS, aTelemetryKey, start); NS_DispatchToMainThread(NS_NewRunnableFunction( "SpawnPrintBackgroundTaskResolution", [holder = std::move(holder), promiseHolder = std::move(promiseHolder), + telemetryKey = std::move(aTelemetryKey), startRoundTrip, result = std::move(result)] { + Telemetry::AccumulateTimeDelta( + Telemetry::PRINT_BACKGROUND_TASK_ROUND_TRIP_TIME_MS, + telemetryKey, startRoundTrip); ResolveOrReject(*promiseHolder->get(), *holder->get(), result); })); @@ -69,6 +78,7 @@ void SpawnPrintBackgroundTask( template nsresult PrintBackgroundTaskPromise( T& aReceiver, JSContext* aCx, dom::Promise** aResultPromise, + const nsCString& aTelemetryKey, PrintBackgroundTask aTask, Args... aArgs) { ErrorResult rv; RefPtr promise = @@ -77,7 +87,7 @@ nsresult PrintBackgroundTaskPromise( return rv.StealNSResult(); } - SpawnPrintBackgroundTask(aReceiver, *promise, aTask, + SpawnPrintBackgroundTask(aReceiver, *promise, aTelemetryKey, aTask, std::forward(aArgs)...); promise.forget(aResultPromise); @@ -89,15 +99,16 @@ nsresult PrintBackgroundTaskPromise( template nsresult AsyncPromiseAttributeGetter( T& aReceiver, RefPtr& aPromiseSlot, JSContext* aCx, - dom::Promise** aResultPromise, + dom::Promise** aResultPromise, const nsCString& aTelemetryKey, PrintBackgroundTask aTask, Args... aArgs) { if (RefPtr existing = aPromiseSlot) { existing.forget(aResultPromise); return NS_OK; } - nsresult rv = PrintBackgroundTaskPromise(aReceiver, aCx, aResultPromise, - aTask, std::forward(aArgs)...); + nsresult rv = + PrintBackgroundTaskPromise(aReceiver, aCx, aResultPromise, aTelemetryKey, + aTask, std::forward(aArgs)...); NS_ENSURE_SUCCESS(rv, rv); aPromiseSlot = *aResultPromise; diff --git a/widget/nsPrinterBase.cpp b/widget/nsPrinterBase.cpp index 051064892f5d..ad0e45c7668b 100644 --- a/widget/nsPrinterBase.cpp +++ b/widget/nsPrinterBase.cpp @@ -76,9 +76,13 @@ nsresult nsPrinterBase::AsyncPromiseAttributeGetter( JSContext* aCx, Promise** aResultPromise, AsyncAttribute aAttribute, BackgroundTask aBackgroundTask, Args... aArgs) { MOZ_ASSERT(NS_IsMainThread()); + + static const EnumeratedArray + attributeKeys{"SupportsDuplex"_ns, "SupportsColor"_ns, + "SupportsCollation"_ns, "PaperList"_ns}; return mozilla::AsyncPromiseAttributeGetter( *this, mAsyncAttributePromises[aAttribute], aCx, aResultPromise, - aBackgroundTask, std::forward(aArgs)...); + attributeKeys[aAttribute], aBackgroundTask, std::forward(aArgs)...); } NS_IMETHODIMP nsPrinterBase::CreateDefaultSettings(JSContext* aCx, @@ -105,6 +109,7 @@ NS_IMETHODIMP nsPrinterBase::CreateDefaultSettings(JSContext* aCx, } return PrintBackgroundTaskPromise(*this, aCx, aResultPromise, + "DefaultSettings"_ns, &nsPrinterBase::DefaultSettings); } @@ -137,7 +142,7 @@ NS_IMETHODIMP nsPrinterBase::GetPaperList(JSContext* aCx, } void nsPrinterBase::QueryMarginsForPaper(Promise& aPromise, uint64_t aPaperId) { - return SpawnPrintBackgroundTask(*this, aPromise, + return SpawnPrintBackgroundTask(*this, aPromise, "MarginsForPaper"_ns, &nsPrinterBase::GetMarginsForPaper, aPaperId); } diff --git a/widget/nsPrinterBase.h b/widget/nsPrinterBase.h index a63cfa5c9d8b..b6e37ae8c07f 100644 --- a/widget/nsPrinterBase.h +++ b/widget/nsPrinterBase.h @@ -55,6 +55,8 @@ class nsPrinterBase : public nsIPrinter { private: enum class AsyncAttribute { + // If you change this list you must update attributeKeys in + // nsPrinterBase::AsyncPromiseAttributeGetter. SupportsDuplex = 0, SupportsColor, SupportsCollation, diff --git a/widget/nsPrinterListBase.cpp b/widget/nsPrinterListBase.cpp index a4ba7c78956d..67b1c42027d4 100644 --- a/widget/nsPrinterListBase.cpp +++ b/widget/nsPrinterListBase.cpp @@ -51,23 +51,24 @@ void ResolveOrReject(dom::Promise& aPromise, nsPrinterListBase& aList, NS_IMETHODIMP nsPrinterListBase::GetPrinters(JSContext* aCx, Promise** aResult) { - return mozilla::AsyncPromiseAttributeGetter( - *this, mPrintersPromise, aCx, aResult, &nsPrinterListBase::Printers); + return mozilla::AsyncPromiseAttributeGetter(*this, mPrintersPromise, aCx, + aResult, "Printers"_ns, + &nsPrinterListBase::Printers); } NS_IMETHODIMP nsPrinterListBase::GetNamedPrinter(const nsAString& aPrinterName, JSContext* aCx, Promise** aResult) { - return PrintBackgroundTaskPromise(*this, aCx, aResult, + return PrintBackgroundTaskPromise(*this, aCx, aResult, "NamedPrinter"_ns, &nsPrinterListBase::NamedPrinter, nsString{aPrinterName}); } NS_IMETHODIMP nsPrinterListBase::GetNamedOrDefaultPrinter( const nsAString& aPrinterName, JSContext* aCx, Promise** aResult) { - return PrintBackgroundTaskPromise(*this, aCx, aResult, - &nsPrinterListBase::NamedOrDefaultPrinter, - nsString{aPrinterName}); + return PrintBackgroundTaskPromise( + *this, aCx, aResult, "NamedOrDefaultPrinter"_ns, + &nsPrinterListBase::NamedOrDefaultPrinter, nsString{aPrinterName}); } Maybe nsPrinterListBase::NamedOrDefaultPrinter(