summaryrefslogtreecommitdiffstats
path: root/python/mach/mach/telemetry_interface.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mach/mach/telemetry_interface.py')
-rw-r--r--python/mach/mach/telemetry_interface.py77
1 files changed, 77 insertions, 0 deletions
diff --git a/python/mach/mach/telemetry_interface.py b/python/mach/mach/telemetry_interface.py
new file mode 100644
index 0000000000..3ed8ce5674
--- /dev/null
+++ b/python/mach/mach/telemetry_interface.py
@@ -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/.
+
+import sys
+from pathlib import Path
+from typing import Union
+from unittest.mock import Mock
+
+from mach.site import MozSiteMetadata, SitePackagesSource
+
+
+class NoopTelemetry(object):
+ def __init__(self, failed_glean_import):
+ self._failed_glean_import = failed_glean_import
+
+ def metrics(self, metrics_path: Union[str, Path]):
+ return Mock()
+
+ def submit(self, is_bootstrap):
+ if self._failed_glean_import and not is_bootstrap:
+ active_site = MozSiteMetadata.from_runtime()
+ if active_site.mach_site_packages_source == SitePackagesSource.SYSTEM:
+ hint = (
+ "Mach is looking for glean in the system packages. This can be "
+ "resolved by installing it there, or by allowing Mach to run "
+ "without using the system Python packages."
+ )
+ elif active_site.mach_site_packages_source == SitePackagesSource.NONE:
+ hint = (
+ "This is because Mach is currently configured without a source "
+ "for native Python packages."
+ )
+ else:
+ hint = "You may need to run |mach bootstrap|."
+
+ print(
+ f"Glean could not be found, so telemetry will not be reported. {hint}",
+ file=sys.stderr,
+ )
+
+
+class GleanTelemetry(object):
+ """Records and sends Telemetry using Glean.
+
+ Metrics are defined in python/mozbuild/metrics.yaml.
+ Pings are defined in python/mozbuild/pings.yaml.
+
+ The "metrics" and "pings" properties may be replaced with no-op implementations if
+ Glean isn't available. This allows consumers to report telemetry without having
+ to guard against incompatible environments.
+
+ Also tracks whether an employee was just automatically opted into telemetry
+ during this mach invocation.
+ """
+
+ def __init__(
+ self,
+ ):
+ self._metrics_cache = {}
+
+ def metrics(self, metrics_path: Union[str, Path]):
+ if metrics_path not in self._metrics_cache:
+ from glean import load_metrics
+
+ metrics = load_metrics(metrics_path)
+ self._metrics_cache[metrics_path] = metrics
+
+ return self._metrics_cache[metrics_path]
+
+ def submit(self, _):
+ from pathlib import Path
+
+ from glean import load_pings
+
+ pings = load_pings(Path(__file__).parent.parent / "pings.yaml")
+ pings.usage.submit()