Bug 1905928 - Part 3: Add glean telemetry entries r=emilio,win-reviewers,handyman

Each provider has different fallback behavior:
* Windows/macOS: Fallback only on error
* Gpsd/Portal: Fallback only on timeout
* Geoclue: Fallback on both

To meet all the behaviors MLSFallback got FallbackReason/ShutdownReason and report via Glean based on that.

Differential Revision: https://phabricator.services.mozilla.com/D216085
This commit is contained in:
Kagami Sascha Rosylight 2024-07-15 14:58:25 +00:00
Родитель 55a20bfb09
Коммит 214b1c9fc1
12 изменённых файлов: 209 добавлений и 21 удалений

Просмотреть файл

@ -12,6 +12,7 @@
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/GeolocationPositionError.h"
#include "mozilla/dom/GeolocationPositionErrorBinding.h"
#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPrefs_geo.h"
@ -147,6 +148,7 @@ class nsGeolocationRequest final : public ContentPermissionRequestBase,
int32_t mWatchId;
bool mShutdown;
bool mSeenAnySignal = false;
nsCOMPtr<nsIEventTarget> mMainThreadSerialEventTarget;
};
@ -420,19 +422,46 @@ nsIPrincipal* nsGeolocationRequest::GetPrincipal() {
NS_IMETHODIMP
nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition) {
if (!mSeenAnySignal) {
mSeenAnySignal = true;
glean::geolocation::request_result
.EnumGet(glean::geolocation::RequestResultLabel::eSuccess)
.Add();
}
nsCOMPtr<nsIRunnable> ev = new RequestSendLocationEvent(aPosition, this);
mMainThreadSerialEventTarget->Dispatch(ev.forget());
return NS_OK;
}
static glean::geolocation::RequestResultLabel MapErrorToLabel(
uint16_t aErrorCode) {
using Label = glean::geolocation::RequestResultLabel;
switch (aErrorCode) {
case GeolocationPositionError_Binding::PERMISSION_DENIED:
return Label::ePermissionDenied;
case GeolocationPositionError_Binding::POSITION_UNAVAILABLE:
return Label::ePositionUnavailable;
case GeolocationPositionError_Binding::TIMEOUT:
return Label::eTimeout;
default:
MOZ_CRASH("Unknown geolocation error label");
return Label::ePositionUnavailable;
}
}
NS_IMETHODIMP
nsGeolocationRequest::NotifyError(uint16_t aErrorCode) {
MOZ_LOG(
gGeolocationLog, LogLevel::Debug,
("nsGeolocationRequest::NotifyError with error code: %u", aErrorCode));
MOZ_ASSERT(NS_IsMainThread());
if (!mSeenAnySignal) {
mSeenAnySignal = true;
glean::geolocation::request_result.EnumGet(MapErrorToLabel(aErrorCode))
.Add();
}
RefPtr<GeolocationPositionError> positionError =
new GeolocationPositionError(mLocator, aErrorCode);
new GeolocationPositionError(mLocator, static_cast<int16_t>(aErrorCode));
positionError->NotifyCallback(mErrorCallback);
return NS_OK;
}
@ -510,6 +539,9 @@ nsresult nsGeolocationService::Init() {
mProvider = new PortalLocationProvider();
MOZ_LOG(gGeolocationLog, LogLevel::Debug,
("Selected PortalLocationProvider"));
glean::geolocation::linux_provider
.EnumGet(glean::geolocation::LinuxProviderLabel::ePortal)
.Set(true);
}
// Geoclue includes GPS data so it has higher priority than raw GPSD
if (!mProvider && StaticPrefs::geo_provider_use_geoclue()) {
@ -522,6 +554,9 @@ nsresult nsGeolocationService::Init() {
mProvider = std::move(gcProvider);
MOZ_LOG(gGeolocationLog, LogLevel::Debug,
("Selected GeoclueLocationProvider"));
glean::geolocation::linux_provider
.EnumGet(glean::geolocation::LinuxProviderLabel::eGeoclue)
.Set(true);
}
}
# ifdef MOZ_GPSD
@ -529,6 +564,9 @@ nsresult nsGeolocationService::Init() {
mProvider = new GpsdLocationProvider();
MOZ_LOG(gGeolocationLog, LogLevel::Debug,
("Selected GpsdLocationProvider"));
glean::geolocation::linux_provider
.EnumGet(glean::geolocation::LinuxProviderLabel::eGpsd)
.Set(true);
}
# endif
# endif
@ -920,7 +958,10 @@ Geolocation::Update(nsIDOMGeoPosition* aSomewhere) {
double accuracy = -1;
coords->GetAccuracy(&accuracy);
mozilla::Telemetry::Accumulate(
mozilla::Telemetry::GEOLOCATION_ACCURACY_EXPONENTIAL, accuracy);
mozilla::Telemetry::GEOLOCATION_ACCURACY_EXPONENTIAL,
static_cast<uint32_t>(accuracy));
glean::geolocation::accuracy.AccumulateSingleSample(
static_cast<uint64_t>(accuracy));
}
}

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsIGeolocationProvider.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/Logging.h"
#include "mozilla/glean/GleanMetrics.h"
extern mozilla::LazyLogModule gGeolocationLog;
@ -19,7 +20,21 @@ MLSFallback::MLSFallback(uint32_t delay) : mDelayMs(delay) {}
MLSFallback::~MLSFallback() = default;
nsresult MLSFallback::Startup(nsIGeolocationUpdate* aWatcher) {
mozilla::glean::geolocation::FallbackLabel MapReasonToLabel(
MLSFallback::FallbackReason aReason) {
switch (aReason) {
case MLSFallback::FallbackReason::Error:
return mozilla::glean::geolocation::FallbackLabel::eOnError;
case MLSFallback::FallbackReason::Timeout:
return mozilla::glean::geolocation::FallbackLabel::eOnTimeout;
default:
MOZ_CRASH("Unexpected fallback reason");
return mozilla::glean::geolocation::FallbackLabel::eOnError;
}
}
nsresult MLSFallback::Startup(nsIGeolocationUpdate* aWatcher,
FallbackReason aReason) {
if (mHandoffTimer || mMLSFallbackProvider) {
return NS_OK;
}
@ -28,6 +43,8 @@ nsresult MLSFallback::Startup(nsIGeolocationUpdate* aWatcher) {
// No need to schedule a timer callback if there is no startup delay.
if (mDelayMs == 0) {
mozilla::glean::geolocation::fallback.EnumGet(MapReasonToLabel(aReason))
.Add();
return CreateMLSFallbackProvider();
}
@ -35,7 +52,13 @@ nsresult MLSFallback::Startup(nsIGeolocationUpdate* aWatcher) {
nsITimer::TYPE_ONE_SHOT);
}
nsresult MLSFallback::Shutdown() {
nsresult MLSFallback::Shutdown(ShutdownReason aReason) {
if (aReason == ShutdownReason::ProviderResponded) {
mozilla::glean::geolocation::fallback
.EnumGet(mozilla::glean::geolocation::FallbackLabel::eNone)
.Add();
}
mUpdateWatcher = nullptr;
if (mHandoffTimer) {
@ -52,7 +75,12 @@ nsresult MLSFallback::Shutdown() {
}
NS_IMETHODIMP
MLSFallback::Notify(nsITimer* aTimer) { return CreateMLSFallbackProvider(); }
MLSFallback::Notify(nsITimer* aTimer) {
mozilla::glean::geolocation::fallback
.EnumGet(mozilla::glean::geolocation::FallbackLabel::eOnTimeout)
.Add();
return CreateMLSFallbackProvider();
}
NS_IMETHODIMP
MLSFallback::GetName(nsACString& aName) {

Просмотреть файл

@ -35,8 +35,19 @@ class MLSFallback : public nsITimerCallback, public nsINamed {
NS_DECL_NSINAMED
explicit MLSFallback(uint32_t delayMs = 2000);
nsresult Startup(nsIGeolocationUpdate* aWatcher);
nsresult Shutdown();
enum class FallbackReason : uint8_t {
Error,
Timeout,
};
nsresult Startup(nsIGeolocationUpdate* aWatcher,
FallbackReason aReason = FallbackReason::Error);
enum class ShutdownReason : uint8_t {
ProviderResponded,
ProviderShutdown,
};
nsresult Shutdown(ShutdownReason aReason);
private:
nsresult CreateMLSFallbackProvider();

Просмотреть файл

@ -0,0 +1,77 @@
# 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/.
# Adding a new metric? We have docs for that!
# https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/new_definitions_file.html
---
$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
$tags:
- 'Core :: DOM: Geolocation'
geolocation:
accuracy:
type: custom_distribution
description: >
Accuracy returned by the Geolocation API
range_min: 1
range_max: 66355200
bucket_count: 50
histogram_type: exponential
unit: accuracy radius
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1905928
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1905928
notification_emails:
- krosylight@mozilla.com
expires: never
request_result:
type: labeled_counter
description: >
The result for each geolocation request. Success label will only happen
once for each request, even if it's a watch request.
labels:
- success
- permission_denied
- position_unavailable
- timeout
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1905928
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1905928
notification_emails:
- krosylight@mozilla.com
expires: never
fallback:
type: labeled_counter
description: >
Whether the default provider falled back to NetworkGeolocationProvider.
labels:
- none
- on_error
- on_timeout
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1905928
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1905928
notification_emails:
- krosylight@mozilla.com
expires: never
linux_provider:
type: labeled_boolean
description: >
Which system provider are we using on Linux
labels:
- none
- portal
- geoclue
- gpsd
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1905928
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1905928
notification_emails:
- krosylight@mozilla.com
expires: never

Просмотреть файл

@ -21,6 +21,7 @@
#include "mozilla/XREAppData.h"
#include "mozilla/dom/GeolocationPosition.h"
#include "mozilla/dom/GeolocationPositionErrorBinding.h"
#include "mozilla/glean/GleanMetrics.h"
#include "MLSFallback.h"
#include "nsAppRunner.h"
#include "nsCOMPtr.h"
@ -237,7 +238,7 @@ class GCLocProviderPriv final : public nsIGeolocationProvider,
void DoShutdown(bool aDeleteClient, bool aDeleteManager);
void DoShutdownClearCallback(bool aDestroying);
nsresult FallbackToMLS();
nsresult FallbackToMLS(MLSFallback::FallbackReason aReason);
void StopMLSFallback();
void WatchStart();
@ -328,17 +329,23 @@ void GCLocProviderPriv::Update(nsIDOMGeoPosition* aPosition) {
void GCLocProviderPriv::UpdateLastPosition() {
MOZ_DIAGNOSTIC_ASSERT(mLastPosition, "No last position to update");
if (mMLSFallbackTimer) {
// We are not going to wait for MLS fallback anymore
glean::geolocation::fallback
.EnumGet(glean::geolocation::FallbackLabel::eNone)
.Add();
}
StopPositionTimer();
StopMLSFallbackTimer();
Update(mLastPosition);
}
nsresult GCLocProviderPriv::FallbackToMLS() {
nsresult GCLocProviderPriv::FallbackToMLS(MLSFallback::FallbackReason aReason) {
GCL_LOG(Debug, "trying to fall back to MLS");
StopMLSFallback();
RefPtr fallback = new MLSFallback(0);
MOZ_TRY(fallback->Startup(mCallback));
MOZ_TRY(fallback->Startup(mCallback, aReason));
GCL_LOG(Debug, "Started up MLS fallback");
mMLSFallback = std::move(fallback);
@ -351,7 +358,7 @@ void GCLocProviderPriv::StopMLSFallback() {
}
GCL_LOG(Debug, "Clearing MLS fallback");
if (mMLSFallback) {
mMLSFallback->Shutdown();
mMLSFallback->Shutdown(MLSFallback::ShutdownReason::ProviderShutdown);
mMLSFallback = nullptr;
}
}
@ -362,7 +369,7 @@ void GCLocProviderPriv::NotifyError(int aError) {
}
// We errored out, try to fall back to MLS.
if (NS_SUCCEEDED(FallbackToMLS())) {
if (NS_SUCCEEDED(FallbackToMLS(MLSFallback::FallbackReason::Error))) {
return;
}
@ -883,7 +890,7 @@ void GCLocProviderPriv::MLSFallbackTimerFired() {
GCL_LOG(Info,
"Didn't get a location in a reasonable amount of time, trying to "
"fall back to MLS");
FallbackToMLS();
FallbackToMLS(MLSFallback::FallbackReason::Timeout);
}
// Did we made some D-Bus call and are still waiting for its response?
@ -1048,7 +1055,7 @@ GCLocProviderPriv::Watch(nsIGeolocationUpdate* aCallback) {
if (!mProxyManager) {
GCL_LOG(Debug, "watch request falling back to MLS");
return FallbackToMLS();
return FallbackToMLS(MLSFallback::FallbackReason::Error);
}
StopMLSFallback();

Просмотреть файл

@ -340,7 +340,7 @@ void GpsdLocationProvider::Update(nsIDOMGeoPosition* aPosition) {
if (mMLSProvider) {
/* We got a location from gpsd, so let's cancel our MLS fallback. */
mMLSProvider->Shutdown();
mMLSProvider->Shutdown(MLSFallback::ShutdownReason::ProviderResponded);
mMLSProvider = nullptr;
}
@ -425,7 +425,7 @@ GpsdLocationProvider::Watch(nsIGeolocationUpdate* aCallback) {
NS_IMETHODIMP
GpsdLocationProvider::Shutdown() {
if (mMLSProvider) {
mMLSProvider->Shutdown();
mMLSProvider->Shutdown(MLSFallback::ShutdownReason::ProviderShutdown);
mMLSProvider = nullptr;
}

Просмотреть файл

@ -104,7 +104,7 @@ void PortalLocationProvider::Update(nsIDOMGeoPosition* aPosition) {
LOG_PORTAL(
"Update from location portal received: Cancelling fallback MLS "
"provider\n");
mMLSProvider->Shutdown();
mMLSProvider->Shutdown(MLSFallback::ShutdownReason::ProviderResponded);
mMLSProvider = nullptr;
}
@ -339,7 +339,7 @@ PortalLocationProvider::Shutdown() {
mDBUSLocationProxy = nullptr;
}
if (mMLSProvider) {
mMLSProvider->Shutdown();
mMLSProvider->Shutdown(MLSFallback::ShutdownReason::ProviderShutdown);
mMLSProvider = nullptr;
}
return NS_OK;

Просмотреть файл

@ -39,6 +39,7 @@ class CoreLocationLocationProvider : public nsIGeolocationProvider {
void Update(nsIDOMGeoPosition* aSomewhere);
void CreateMLSFallbackProvider();
void CancelMLSFallbackProvider();
bool IsEverUpdated() const { return mEverUpdated; }
private:
virtual ~CoreLocationLocationProvider() = default;
@ -47,6 +48,8 @@ class CoreLocationLocationProvider : public nsIGeolocationProvider {
nsCOMPtr<nsIGeolocationUpdate> mCallback;
RefPtr<MLSFallback> mMLSFallbackProvider;
bool mEverUpdated = false;
class MLSUpdate : public nsIGeolocationUpdate {
public:
NS_DECL_ISUPPORTS

Просмотреть файл

@ -14,6 +14,7 @@
#include "mozilla/Telemetry.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/GeolocationPositionErrorBinding.h"
#include "mozilla/glean/GleanMetrics.h"
#include "MLSFallback.h"
#include <CoreLocation/CLError.h>
@ -106,6 +107,13 @@ static const CLLocationAccuracy kDEFAULT_ACCURACY =
location.horizontalAccuracy, altitudeAccuracy, heading, speed,
PR_Now() / PR_USEC_PER_MSEC);
if (!mProvider->IsEverUpdated()) {
// Saw signal without MLS fallback
glean::geolocation::fallback
.EnumGet(glean::geolocation::FallbackLabel::eNone)
.Add();
}
mProvider->Update(geoPosition);
Telemetry::Accumulate(Telemetry::GEOLOCATION_OSX_SOURCE_IS_MLS, false);
}
@ -208,7 +216,8 @@ CoreLocationLocationProvider::Shutdown() {
mCLObjects = nullptr;
if (mMLSFallbackProvider) {
mMLSFallbackProvider->Shutdown();
mMLSFallbackProvider->Shutdown(
MLSFallback::ShutdownReason::ProviderShutdown);
mMLSFallbackProvider = nullptr;
}
@ -229,6 +238,7 @@ void CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere) {
if (aSomewhere && mCallback) {
mCallback->Update(aSomewhere);
}
mEverUpdated = true;
}
void CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode) {
nsCOMPtr<nsIGeolocationUpdate> callback(mCallback);
@ -248,6 +258,7 @@ void CoreLocationLocationProvider::CancelMLSFallbackProvider() {
return;
}
mMLSFallbackProvider->Shutdown();
mMLSFallbackProvider->Shutdown(
MLSFallback::ShutdownReason::ProviderResponded);
mMLSFallbackProvider = nullptr;
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "WindowsLocationProvider.h"
#include "WindowsLocationParent.h"
#include "mozilla/dom/WindowsUtilsParent.h"
#include "mozilla/glean/GleanMetrics.h"
#include "GeolocationPosition.h"
#include "nsComponentManagerUtils.h"
#include "mozilla/ipc/UtilityProcessManager.h"
@ -218,6 +219,13 @@ void WindowsLocationProvider::RecvUpdate(
mCallback->Update(aGeoPosition.get());
Telemetry::Accumulate(Telemetry::GEOLOCATION_WIN8_SOURCE_IS_MLS, false);
if (!mEverUpdated) {
mEverUpdated = true;
// Saw signal without MLS fallback
glean::geolocation::fallback
.EnumGet(glean::geolocation::FallbackLabel::eNone)
.Add();
}
}
void WindowsLocationProvider::RecvFailed(uint16_t err) {
@ -342,7 +350,7 @@ void WindowsLocationProvider::CancelMLSProvider() {
return;
}
mMLSProvider->Shutdown();
mMLSProvider->Shutdown(MLSFallback::ShutdownReason::ProviderShutdown);
mMLSProvider = nullptr;
}

Просмотреть файл

@ -71,6 +71,7 @@ class WindowsLocationProvider final : public nsIGeolocationProvider {
RefPtr<WindowsLocationParent> mActor;
bool mWatching = false;
bool mEverUpdated = false;
};
} // namespace mozilla::dom

Просмотреть файл

@ -18,6 +18,7 @@ gecko_metrics = [
"browser/base/content/metrics.yaml",
"docshell/base/metrics.yaml",
"dom/base/use_counter_metrics.yaml",
"dom/geolocation/metrics.yaml",
"dom/media/eme/metrics.yaml",
"dom/media/hls/metrics.yaml",
"dom/media/metrics.yaml",