Bug 1477213 - Replace cpp_guard with operating_systems for compile-time OS check. r=gfritzsche
authorJan-Erik Rediger <jrediger@mozilla.com>
Mon, 27 Aug 2018 14:23:34 +0000
changeset 488605 600af91dfc45a4517375ab5b08da82e7d0c9efa6
parent 488604 5ccb4b6527c17cad6ba6ce9441ead357ed9be6c6
child 488606 fcd411537143c5d926136eb3aa39a6ff677bf326
push id9734
push usershindli@mozilla.com
push dateThu, 30 Aug 2018 12:18:07 +0000
treeherdermozilla-beta@71c71ab3afae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgfritzsche
bugs1477213
milestone63.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 1477213 - Replace cpp_guard with operating_systems for compile-time OS check. r=gfritzsche `cpp_guard` was only used for operating system checks. We can check this value in our Python build scripts and exclude histograms that shouldn't be included for the target OS. Differential Revision: https://phabricator.services.mozilla.com/D2927
toolkit/components/telemetry/Histograms.json
toolkit/components/telemetry/docs/collection/histograms.rst
toolkit/components/telemetry/gen_histogram_data.py
toolkit/components/telemetry/gen_histogram_enum.py
toolkit/components/telemetry/parse_histograms.py
toolkit/components/telemetry/shared_telemetry_utils.py
toolkit/components/telemetry/tests/unit/test_TelemetryHistograms.js
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1095,50 +1095,50 @@
   "LOW_MEMORY_EVENTS_VIRTUAL": {
     "record_in_processes": ["main"],
     "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 1024,
     "n_buckets": 21,
     "description": "Number of low-virtual-memory events fired since last ping",
-    "cpp_guard": "XP_WIN",
+    "operating_systems": ["windows"],
     "bug_numbers": [711490,1451005]
   },
   "LOW_MEMORY_EVENTS_PHYSICAL": {
     "record_in_processes": ["main"],
     "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 1024,
     "n_buckets": 21,
     "description": "Number of low-physical-memory events fired since last ping",
-    "cpp_guard": "XP_WIN",
+    "operating_systems": ["windows"],
     "bug_numbers": [711490,1451005]
   },
   "LOW_MEMORY_EVENTS_COMMIT_SPACE": {
     "record_in_processes": ["main"],
     "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 1024,
     "n_buckets": 21,
     "description": "Number of low-commit-space events fired since last ping",
-    "cpp_guard": "XP_WIN",
+    "operating_systems": ["windows"],
     "bug_numbers": [1451005]
   },
   "PAGE_FAULTS_HARD": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "default",
     "kind": "exponential",
     "low": 8,
     "high": 65536,
     "n_buckets": 13,
     "description": "Hard page faults (since last telemetry ping)",
-    "cpp_guard": "XP_UNIX"
+    "operating_systems": ["unix"]
   },
   "FONTLIST_INITOTHERFAMILYNAMES": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 30000,
     "n_buckets": 50,
     "description": "Time(ms) spent on reading other family names from all fonts"
@@ -1161,61 +1161,61 @@
   },
   "DWRITEFONT_DELAYEDINITFONTLIST_TOTAL": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 30000,
     "n_buckets": 10,
     "description": "gfxDWriteFontList::DelayedInitFontList Total (ms)",
-    "cpp_guard": "XP_WIN"
+    "operating_systems": ["windows"]
   },
   "DWRITEFONT_DELAYEDINITFONTLIST_COUNT": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 10000,
     "n_buckets": 10,
     "description": "gfxDWriteFontList::DelayedInitFontList Font Family Count",
-    "cpp_guard": "XP_WIN"
+    "operating_systems": ["windows"]
   },
   "DWRITEFONT_DELAYEDINITFONTLIST_COLLECT": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 30000,
     "n_buckets": 10,
     "description": "gfxDWriteFontList::DelayedInitFontList GetSystemFontCollection (ms)",
-    "cpp_guard": "XP_WIN"
+    "operating_systems": ["windows"]
   },
   "DWRITEFONT_INIT_PROBLEM": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 8,
     "description": "DirectWrite system fontlist initialization problem (1=GDI interop, 2=system font collection, 3=no fonts)",
-    "cpp_guard": "XP_WIN"
+    "operating_systems": ["windows"]
   },
   "GDI_INITFONTLIST_TOTAL": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 30000,
     "n_buckets": 10,
     "description": "gfxGDIFontList::InitFontList Total (ms)",
-    "cpp_guard": "XP_WIN"
+    "operating_systems": ["windows"]
   },
   "MAC_INITFONTLIST_TOTAL": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 30000,
     "n_buckets": 10,
     "description": "gfxMacPlatformFontList::InitFontList Total (ms)",
-    "cpp_guard": "XP_DARWIN"
+    "operating_systems": ["mac"]
   },
   "SYSTEM_FONT_FALLBACK": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 100000,
     "n_buckets": 50,
     "description": "System font fallback (us)"
@@ -5028,62 +5028,62 @@
     "bug_numbers": [1399880],
     "description": "The size of the description and preview image url for page metadata (Bytes)"
   },
   "FENNEC_DISTRIBUTION_REFERRER_INVALID": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Whether the referrer intent specified an invalid distribution name",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_DISTRIBUTION_CODE_CATEGORY": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 20,
     "description": "First digit of HTTP result code, or error category, during distribution download",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_DISTRIBUTION_DOWNLOAD_TIME_MS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 100,
     "high": 40000,
     "n_buckets": 30,
     "description": "Time taken to download a specified distribution file (msec)",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_BOOKMARKS_COUNT": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "60",
     "kind": "exponential",
     "high": 8000,
     "n_buckets": 20,
     "description": "Number of bookmarks stored in the browser DB",
     "alert_emails": ["mobile-frontend@mozilla.com"],
     "bug_numbers": [1244704]
   },
   "FENNEC_ORBOT_INSTALLED": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "70",
     "kind": "flag",
-    "cpp_guard": "ANDROID",
+    "operating_systems": ["android"],
     "description": "Whether or not users have Orbot installed",
     "alert_emails": ["seceng@mozilla.org"],
     "bug_numbers": [1314784]
   },
   "FENNEC_READING_LIST_COUNT": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "50",
     "kind": "exponential",
     "high": 1000,
     "n_buckets": 10,
-    "cpp_guard": "ANDROID",
+    "operating_systems": ["android"],
     "description": "Number of reading list items stored in the browser DB *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
   },
   "FENNEC_READER_VIEW_CACHE_SIZE": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "60",
     "alert_emails": ["mobile-frontend@mozilla.com"],
     "kind": "exponential",
     "low": 32,
@@ -5097,29 +5097,29 @@
     "expires_in_version": "55",
     "alert_emails": ["mobile-platform@mozilla.org"],
     "kind": "exponential",
     "low": 10,
     "high": 10485760,
     "n_buckets": 22,
     "description": "Latency in microseconds of UI events in the Android event loop between posting and processing",
     "bug_numbers": [1322574],
-    "cpp_guard": "MOZ_WIDGET_ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_LOOP_OTHER_LATENCY": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "55",
     "alert_emails": ["mobile-platform@mozilla.org"],
     "kind": "exponential",
     "low": 10,
     "high": 10485760,
     "n_buckets": 22,
     "description": "Latency in microseconds of non-UI events in the Android event loop between posting and processing",
     "bug_numbers": [1322574],
-    "cpp_guard": "MOZ_WIDGET_ANDROID"
+    "operating_systems": ["android"]
   },
   "PLACES_SORTED_BOOKMARKS_PERC": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "linear",
     "high": 100,
     "n_buckets": 10,
     "description": "PLACES: Percentage of bookmarks organized in folders"
@@ -7621,16 +7621,64 @@
     "kind": "linear",
     "low": 1,
     "high": 10000,
     "n_buckets": 10,
     "bug_numbers": [1452552],
     "description": "a testing histogram; not meant to be touched",
     "products": ["fennec", "geckoview"]
   },
+  "TELEMETRY_TEST_OS_ANDROID_ONLY": {
+    "record_in_processes": ["all"],
+    "alert_emails": ["telemetry-client-dev@mozilla.com"],
+    "expires_in_version": "never",
+    "kind": "linear",
+    "low": 1,
+    "high": 10000,
+    "n_buckets": 10,
+    "bug_numbers": [1477213],
+    "description": "a testing histogram; not meant to be touched",
+    "operating_systems": ["android"]
+  },
+  "TELEMETRY_TEST_OS_WIN_ONLY": {
+    "record_in_processes": ["all"],
+    "alert_emails": ["telemetry-client-dev@mozilla.com"],
+    "expires_in_version": "never",
+    "kind": "linear",
+    "low": 1,
+    "high": 10000,
+    "n_buckets": 10,
+    "bug_numbers": [1477213],
+    "description": "a testing histogram; not meant to be touched",
+    "operating_systems": ["windows"]
+  },
+  "TELEMETRY_TEST_OS_LINUX_ONLY": {
+    "record_in_processes": ["all"],
+    "alert_emails": ["telemetry-client-dev@mozilla.com"],
+    "expires_in_version": "never",
+    "kind": "linear",
+    "low": 1,
+    "high": 10000,
+    "n_buckets": 10,
+    "bug_numbers": [1477213],
+    "description": "a testing histogram; not meant to be touched",
+    "operating_systems": ["linux"]
+  },
+  "TELEMETRY_TEST_OS_MAC_ONLY": {
+    "record_in_processes": ["all"],
+    "alert_emails": ["telemetry-client-dev@mozilla.com"],
+    "expires_in_version": "never",
+    "kind": "linear",
+    "low": 1,
+    "high": 10000,
+    "n_buckets": 10,
+    "bug_numbers": [1477213],
+    "description": "a testing histogram; not meant to be touched",
+    "operating_systems": ["mac"]
+  },
   "STARTUP_CRASH_DETECTED": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Whether there was a crash during the last startup"
   },
   "SAFE_MODE_USAGE": {
     "record_in_processes": ["main", "content"],
@@ -7677,133 +7725,133 @@
   },
   "BROWSERPROVIDER_XUL_IMPORT_BOOKMARKS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "default",
     "kind": "exponential",
     "high": 50000,
     "n_buckets": 20,
     "description": "Number of bookmarks in the original XUL places database",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_GLOBALHISTORY_ADD_MS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time for a record to be added to history (ms)",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_GLOBALHISTORY_UPDATE_MS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time for a record to be updated in history (ms)",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_GLOBALHISTORY_VISITED_BUILD_MS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time to update the visited link set (ms)",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_RESTORING_ACTIVITY": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Fennec is starting up but the Gecko thread was still running",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_SEARCH_LOADER_TIME_MS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time for a URL bar DB search to return (ms)",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_STARTUP_TIME_GECKOREADY": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 500,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time for the Gecko:Ready message to arrive (ms)",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_STARTUP_TIME_JAVAUI": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 100,
     "high": 5000,
     "n_buckets": 20,
     "description": "Time for the Java UI to load (ms)",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_TOPSITES_LOADER_TIME_MS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time for the home screen Top Sites query to return with no filter set (ms)",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_ACTIVITY_STREAM_TOPSITES_LOADER_TIME_MS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time for the Activity Stream home screen Top Sites query to return (ms)",
     "alert_emails": ["mobile-frontend@mozilla.com"],
     "bug_numbers": [1293790],
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_ACTIVITY_STREAM_HIGHLIGHTS_LOADER_TIME_MS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time for the Activity Stream highlights query to return (ms)",
     "alert_emails": ["mobile-frontend@mozilla.com"],
     "bug_numbers": [1298786],
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_HOMEPANELS_CUSTOM": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "54",
     "kind": "boolean",
     "bug_numbers": [1245368],
     "description": "Whether the user has customized their homepanels",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_WAS_KILLED": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Killed, likely due to an OOM condition",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FIPS_ENABLED": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["seceng@mozilla.org"],
     "expires_in_version": "54",
     "kind": "flag",
     "bug_numbers": [1241317],
     "releaseChannelCollection": "opt-out",
@@ -7982,17 +8030,17 @@
   "TOUCH_ENABLED_DEVICE": {
     "record_in_processes": ["main"],
     "expires_in_version": "never",
     "kind": "boolean",
     "releaseChannelCollection": "opt-out",
     "bug_numbers": [795307, 1390269],
     "alert_emails": ["jimm@mozilla.com"],
     "description": "Boolean indicating if a touch input device is detected.",
-    "cpp_guard": "XP_WIN"
+    "operating_systems": ["windows"]
   },
   "COMPONENTS_SHIM_ACCESSED_BY_CONTENT": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Whether content ever accesed the Components shim in this session"
   },
   "CHECK_ADDONS_MODIFIED_MS": {
@@ -12574,85 +12622,85 @@
     "description": "Each key is the message name, with digits removed, from an async message manager message that was rejected for being over approximately 128MB, recorded in the sending process at the time of sending."
   },
   "SANDBOX_HAS_SECCOMP_BPF": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
     "kind": "boolean",
-    "cpp_guard": "XP_LINUX",
+    "operating_systems": ["linux"],
     "description": "Whether the system has seccomp-bpf capability"
   },
   "SANDBOX_HAS_SECCOMP_TSYNC": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428, 1370578],
     "expires_in_version": "61",
     "kind": "boolean",
-    "cpp_guard": "XP_LINUX",
+    "operating_systems": ["linux"],
     "description": "Whether the system has seccomp-bpf thread-sync capability"
   },
   "SANDBOX_HAS_USER_NAMESPACES": {
     "record_in_processes": ["main"],
     "alert_emails": ["gcp@mozilla.com", "jld@mozilla.com"],
     "bug_numbers": [1098428, 1370578, 1461546],
     "expires_in_version": "65",
     "releaseChannelCollection": "opt-out",
     "kind": "boolean",
-    "cpp_guard": "XP_LINUX",
+    "operating_systems": ["linux"],
     "description": "Whether our process succedeed in creating a user namespace"
   },
   "SANDBOX_HAS_USER_NAMESPACES_PRIVILEGED": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428, 1370578],
     "expires_in_version": "61",
     "kind": "boolean",
-    "cpp_guard": "XP_LINUX",
+    "operating_systems": ["linux"],
     "description": "Whether the system has the capability to create privileged user namespaces"
   },
  "SANDBOX_MEDIA_ENABLED": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
     "kind": "boolean",
-    "cpp_guard": "XP_LINUX",
+    "operating_systems": ["linux"],
     "description": "Whether the sandbox is enabled for media/GMP plugins"
   },
  "SANDBOX_CONTENT_ENABLED": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
     "kind": "boolean",
-    "cpp_guard": "XP_LINUX",
+    "operating_systems": ["linux"],
     "description": "Whether the sandbox is enabled for the content process"
   },
   "SANDBOX_REJECTED_SYSCALLS": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["jld@mozilla.com", "gcp@mozilla.com"],
     "bug_numbers": [1286865],
     "expires_in_version": "never",
     "releaseChannelCollection": "opt-out",
     "kind": "count",
     "keyed": true,
-    "cpp_guard": "XP_LINUX",
+    "operating_systems": ["linux"],
     "description": "System calls blocked by a seccomp-bpf sandbox policy; limited to syscalls where we would crash on Nightly.  The key is generally the architecture and syscall ID but in some cases we include non-personally-identifying information from the syscall arguments; see the function SubmitToTelemetry in security/sandbox/linux/reporter/SandboxReporter.cpp for details."
   },
   "SANDBOX_FAILED_LAUNCH_KEYED": {
     "record_in_processes": ["main"],
     "alert_emails": ["bowen@mozilla.com"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "keyed": true,
     "n_values": 50,
     "bug_numbers": [1368600],
-    "cpp_guard": "XP_WIN",
+    "operating_systems": ["windows"],
     "description": "Error code when a Windows sandboxed process fails to launch, keyed by process type and Windows error code. See https://dxr.mozilla.org/mozilla-central/search?q=ResultCode++path%3Asandbox_types.h&redirect=true for definitions of the error codes."
   },
   "SYNC_WORKER_OPERATION": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["amarchesini@mozilla.com", "khuey@mozilla.com" ],
     "bug_numbers": [1267904],
     "expires_in_version": "never",
     "kind": "exponential",
@@ -12814,35 +12862,35 @@
   },
   "FENNEC_SESSIONSTORE_DAMAGED_SESSION_FILE": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["jh+bugzilla@buttercookie.de"],
     "expires_in_version": "66",
     "kind": "flag",
     "bug_numbers": [1284017],
     "description": "When restoring tabs on startup, reading from sessionstore.js failed, even though the file exists and is not containing an explicitly empty window.",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_SESSIONSTORE_RESTORING_FROM_BACKUP": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["jh+bugzilla@buttercookie.de"],
     "expires_in_version": "66",
     "kind": "flag",
     "bug_numbers": [1190627],
     "description": "When restoring tabs on startup, reading from sessionstore.js failed, but sessionstore.bak was read successfully.",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "FENNEC_SESSIONSTORE_ALL_FILES_DAMAGED": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["jh+bugzilla@buttercookie.de"],
     "expires_in_version": "66",
     "kind": "flag",
     "bug_numbers": [1337115],
     "description": "Both the main session file and its backup could not be read and and the first run pref is false.",
-    "cpp_guard": "ANDROID"
+    "operating_systems": ["android"]
   },
   "NUMBER_OF_PROFILES": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["amarchesini@mozilla.com"],
     "expires_in_version": "59",
     "bug_numbers": [1296606],
     "kind": "count",
     "description": "Number of named browser profiles for the current user, as reported by the profile service at startup."
--- a/toolkit/components/telemetry/docs/collection/histograms.rst
+++ b/toolkit/components/telemetry/docs/collection/histograms.rst
@@ -179,20 +179,34 @@ Required for categorical histograms. Thi
 ``bug_numbers``
 ---------------
 Required for all new histograms. This is an array of integers and should at least contain the bug number that added the probe and additionally other bug numbers that affected its behavior.
 
 ``description``
 ---------------
 Required. A description of the data tracked by the histogram, e.g. _"Resident memory size"_
 
-``cpp_guard``
--------------
+``cpp_guard`` (obsolete, use ``operating_systems``)
+---------------------------------------------------
 Optional. This field inserts an #ifdef directive around the histogram's C++ declaration. This is typically used for platform-specific histograms, e.g. ``"cpp_guard": "ANDROID"``
 
+``operating_systems``
+---------------------
+Optional. This field restricts recording to certain operating systems only. Use that in-place of previous ``cpp_guards`` to avoid inclusion on not-specified operating systems.
+Currently supported values are:
+
+- ``mac``
+- ``linux``
+- ``windows``
+- ``android``
+- ``unix``
+- ``all`` (record on all operating systems)
+
+If this field is left out it defaults to ``all``.
+
 ``releaseChannelCollection``
 ----------------------------
 Optional. This is one of:
 
 * ``"opt-in"``: (default value) This histogram is submitted by default on pre-release channels, unless the user opts out.
 * ``"opt-out"``: This histogram is submitted by default on release and pre-release channels, unless the user opts out.
 
 .. warning::
--- a/toolkit/components/telemetry/gen_histogram_data.py
+++ b/toolkit/components/telemetry/gen_histogram_data.py
@@ -5,43 +5,40 @@
 # Write out histogram information for C++.  The histograms are defined
 # in a file provided as a command-line argument.
 
 from __future__ import print_function
 from shared_telemetry_utils import StringTable, static_assert, ParserError
 
 import sys
 import parse_histograms
+import buildconfig
 
 banner = """/* This file is auto-generated, see gen_histogram_data.py.  */
 """
 
 
 def print_array_entry(output, histogram, name_index, exp_index, label_index,
                       label_count, key_index, key_count):
-    cpp_guard = histogram.cpp_guard()
-    if cpp_guard:
-        print("#if defined(%s)" % cpp_guard, file=output)
-    print("  { %s, %s, %s, %s, %d, %d, %s, %d, %d, %d, %d, %s, %s, %s },"
-          % (histogram.low(),
-             histogram.high(),
-             histogram.n_buckets(),
-             histogram.nsITelemetry_kind(),
-             name_index,
-             exp_index,
-             histogram.dataset(),
-             label_index,
-             label_count,
-             key_index,
-             key_count,
-             " | ".join(histogram.record_in_processes_enum()),
-             "true" if histogram.keyed() else "false",
-             " | ".join(histogram.products_enum())), file=output)
-    if cpp_guard:
-        print("#endif", file=output)
+    if histogram.record_on_os(buildconfig.substs["OS_TARGET"]):
+        print("  { %s, %s, %s, %s, %d, %d, %s, %d, %d, %d, %d, %s, %s, %s },"
+              % (histogram.low(),
+                 histogram.high(),
+                 histogram.n_buckets(),
+                 histogram.nsITelemetry_kind(),
+                 name_index,
+                 exp_index,
+                 histogram.dataset(),
+                 label_index,
+                 label_count,
+                 key_index,
+                 key_count,
+                 " | ".join(histogram.record_in_processes_enum()),
+                 "true" if histogram.keyed() else "false",
+                 " | ".join(histogram.products_enum())), file=output)
 
 
 def write_histogram_table(output, histograms):
     string_table = StringTable()
     label_table = []
     label_count = 0
     keys_table = []
     keys_count = 0
@@ -185,31 +182,27 @@ def write_histogram_ranges(output, histo
             # expected format.
             offset += len(ranges) + 1
             print(','.join(map(str, ranges)), ',INT_MAX,', file=output)
     print("0};", file=output)
 
     if offset > 32767:
         raise Exception('Histogram offsets exceeded maximum value for an int16_t.')
 
+    target_os = buildconfig.substs["OS_TARGET"]
     print("#if defined(_MSC_VER) && !defined(__clang__)", file=output)
     print("const int16_t gHistogramBucketLowerBoundIndex[] = {", file=output)
     print("#else", file=output)
     print("constexpr int16_t gHistogramBucketLowerBoundIndex[] = {", file=output)
     print("#endif", file=output)
     for histogram in histograms:
-        cpp_guard = histogram.cpp_guard()
-        if cpp_guard:
-            print("#if defined(%s)" % cpp_guard, file=output)
+        if histogram.record_on_os(target_os):
+            our_offset = ranges_offsets[tuple(histogram.ranges())]
+            print("%d," % our_offset, file=output)
 
-        our_offset = ranges_offsets[tuple(histogram.ranges())]
-        print("%d," % our_offset, file=output)
-
-        if cpp_guard:
-            print("#endif", file=output)
     print("};", file=output)
 
 
 def main(output, *filenames):
     try:
         histograms = list(parse_histograms.from_files(filenames))
     except ParserError as ex:
         print("\nError processing histograms:\n" + str(ex) + "\n")
--- a/toolkit/components/telemetry/gen_histogram_enum.py
+++ b/toolkit/components/telemetry/gen_histogram_enum.py
@@ -13,16 +13,17 @@
 # The histograms are defined in files provided as command-line arguments.
 
 from __future__ import print_function
 from shared_telemetry_utils import ParserError
 
 import parse_histograms
 import itertools
 import sys
+import buildconfig
 
 
 banner = """/* This file is auto-generated, see gen_histogram_enum.py.  */
 """
 
 header = """
 #ifndef mozilla_TelemetryHistogramEnums_h
 #define mozilla_TelemetryHistogramEnums_h
@@ -67,22 +68,18 @@ def main(output, *filenames):
         # The HistogramDUMMY* enum variables are used to make the computation
         # of Histogram{First,Last}UseCounter easier.  Otherwise, we'd have to
         # special case the first and last histogram in the group.
         if use_counter_group:
             print("  HistogramFirstUseCounter,", file=output)
             print("  HistogramDUMMY1 = HistogramFirstUseCounter - 1,", file=output)
 
         for histogram in histograms:
-            cpp_guard = histogram.cpp_guard()
-            if cpp_guard:
-                print("#if defined(%s)" % cpp_guard, file=output)
-            print("  %s," % histogram.name(), file=output)
-            if cpp_guard:
-                print("#endif", file=output)
+            if histogram.record_on_os(buildconfig.substs["OS_TARGET"]):
+                print("  %s," % histogram.name(), file=output)
 
         if use_counter_group:
             print("  HistogramDUMMY2,", file=output)
             print("  HistogramLastUseCounter = HistogramDUMMY2 - 1,", file=output)
 
     print("  HistogramCount,", file=output)
     if seen_use_counters:
         print("  HistogramUseCounterCount = HistogramLastUseCounter -"
--- a/toolkit/components/telemetry/parse_histograms.py
+++ b/toolkit/components/telemetry/parse_histograms.py
@@ -23,17 +23,17 @@ MAX_LABEL_COUNT = 100
 MAX_KEY_COUNT = 30
 MAX_KEY_LENGTH = 20
 MIN_CATEGORICAL_BUCKET_COUNT = 50
 CPP_IDENTIFIER_PATTERN = '^[a-z][a-z0-9_]+[a-z0-9]$'
 
 ALWAYS_ALLOWED_KEYS = [
     'kind',
     'description',
-    'cpp_guard',
+    'operating_systems',
     'expires_in_version',
     'alert_emails',
     'keyed',
     'releaseChannelCollection',
     'bug_numbers',
     'keys',
     'record_in_processes',
     'products',
@@ -117,35 +117,32 @@ class Histogram:
         """Initialize a histogram named name with the given definition.
 definition is a dict-like object that must contain at least the keys:
 
  - 'kind': The kind of histogram.  Must be one of 'boolean', 'flag',
    'count', 'enumerated', 'linear', or 'exponential'.
  - 'description': A textual description of the histogram.
  - 'strict_type_checks': A boolean indicating whether to use the new, stricter type checks.
                          The server-side still has to deal with old, oddly typed submissions,
-                         so we have to skip them there by default.
-
-The key 'cpp_guard' is optional; if present, it denotes a preprocessor
-symbol that should guard C/C++ definitions associated with the histogram."""
+                         so we have to skip them there by default."""
         self._strict_type_checks = strict_type_checks
         self._is_use_counter = name.startswith("USE_COUNTER2_")
         if self._is_use_counter:
             definition.setdefault('record_in_processes', ['main', 'content'])
         self.verify_attributes(name, definition)
         self._name = name
         self._description = definition['description']
         self._kind = definition['kind']
         self._keys = definition.get('keys', [])
-        self._cpp_guard = definition.get('cpp_guard')
         self._keyed = definition.get('keyed', False)
         self._expiration = definition.get('expires_in_version')
         self._labels = definition.get('labels', [])
         self._record_in_processes = definition.get('record_in_processes')
         self._products = definition.get('products', ["all"])
+        self._operating_systems = definition.get('operating_systems', ["all"])
 
         self.compute_bucket_parameters(definition)
         self.set_nsITelemetry_kind()
         self.set_dataset(definition)
 
     def name(self):
         """Return the name of the histogram."""
         return self._name
@@ -176,21 +173,16 @@ the histogram."""
     def high(self):
         """Return the high bound of the histogram."""
         return self._high
 
     def n_buckets(self):
         """Return the number of buckets in the histogram."""
         return self._n_buckets
 
-    def cpp_guard(self):
-        """Return the preprocessor symbol that should guard C/C++ definitions
-associated with the histogram.  Returns None if no guarding is necessary."""
-        return self._cpp_guard
-
     def keyed(self):
         """Returns True if this a keyed histogram, false otherwise."""
         return self._keyed
 
     def keys(self):
         """Returns a list of allowed keys for keyed histogram, [] for others."""
         return self._keys
 
@@ -213,16 +205,33 @@ associated with the histogram.  Returns 
     def products(self):
         """Get the non-empty list of products to record data on"""
         return self._products
 
     def products_enum(self):
         """Get the non-empty list of flags representing products to record data on"""
         return [utils.product_name_to_enum(p) for p in self.products()]
 
+    def operating_systems(self):
+        """Get the list of operating systems to record data on"""
+        return self._operating_systems
+
+    def record_on_os(self, target_os):
+        """Check if this probe should be recorded on the passed os."""
+        os = self.operating_systems()
+        if "all" in os:
+            return True
+
+        canonical_os = utils.canonical_os(target_os)
+
+        if "unix" in os and canonical_os in utils.UNIX_LIKE_OS:
+            return True
+
+        return canonical_os in os
+
     def ranges(self):
         """Return an array of lower bounds for each bucket in the histogram."""
         bucket_fns = {
             'boolean': linear_buckets,
             'flag': linear_buckets,
             'count': linear_buckets,
             'enumerated': linear_buckets,
             'categorical': linear_buckets,
@@ -283,16 +292,17 @@ associated with the histogram.  Returns 
         self.check_keys_field(name, definition)
         self.check_field_types(name, definition)
         self.check_whitelisted_kind(name, definition)
         self.check_whitelistable_fields(name, definition)
         self.check_expiration(name, definition)
         self.check_label_values(name, definition)
         self.check_record_in_processes(name, definition)
         self.check_products(name, definition)
+        self.check_operating_systems(name, definition)
 
     def check_name(self, name):
         if '#' in name:
             ParserError('Error for histogram name "%s": "#" is not allowed.' %
                         (name)).handle_later()
 
         # Avoid C++ identifier conflicts between histogram enums and label enum names.
         if name.startswith("LABELS_"):
@@ -388,16 +398,34 @@ associated with the histogram.  Returns 
             # products is optional
             return
 
         for product in products:
             if not utils.is_valid_product(product):
                 ParserError('Histogram "%s" has unknown product "%s" in %s.\n%s' %
                             (name, product, field, DOC_URL)).handle_later()
 
+    def check_operating_systems(self, name, definition):
+        if not self._strict_type_checks:
+            return
+
+        field = 'operating_systems'
+        operating_systems = definition.get(field)
+
+        DOC_URL = HISTOGRAMS_DOC_URL + "#operating_systems"
+
+        if not operating_systems:
+            # operating_systems is optional
+            return
+
+        for operating_system in operating_systems:
+            if not utils.is_valid_os(operating_system):
+                ParserError('Histogram "%s" has unknown operating system "%s" in %s.\n%s' %
+                            (name, operating_system, field, DOC_URL)).handle_later()
+
     def check_keys_field(self, name, definition):
         keys = definition.get('keys')
         if not self._strict_type_checks or keys is None:
             return
 
         if not definition.get('keyed', False):
             raise ValueError("'keys' field is not valid for %s; only allowed for keyed histograms."
                              % (name))
@@ -417,28 +445,27 @@ associated with the histogram.  Returns 
         # We don't need to run any of these checks on the server.
         if not self._strict_type_checks or whitelists is None:
             return
 
         # Disallow "flag" and "count" histograms on desktop, suggest to use
         # scalars instead. Allow using these histograms on Android, as we
         # don't support scalars there yet.
         hist_kind = definition.get("kind")
-        android_cpp_guard =\
-            definition.get("cpp_guard") in ["ANDROID", "MOZ_WIDGET_ANDROID"]
+        android_target = "android" in definition.get("operating_systems", [])
 
-        if not android_cpp_guard and \
+        if not android_target and \
            hist_kind in ["flag", "count"] and \
            name not in whitelists["kind"]:
             ParserError(('Unsupported kind "%s" for histogram "%s":\n'
                          'New "%s" histograms are not supported on Desktop, you should'
                          ' use scalars instead:\n'
                          '%s\n'
                          'Are you trying to add a histogram on Android?'
-                         ' Add "cpp_guard": "ANDROID" to your histogram definition.')
+                         ' Add "operating_systems": ["android"] to your histogram definition.')
                         % (hist_kind, name, hist_kind, SCALARS_DOC_URL)).handle_now()
 
     # Check for the presence of fields that old histograms are whitelisted for.
     def check_whitelistable_fields(self, name, definition):
         # Use counters don't have any mechanism to add the fields checked here,
         # so skip the check for them.
         # We also don't need to run any of these checks on the server.
         if self._is_use_counter or not self._strict_type_checks:
@@ -463,28 +490,28 @@ associated with the histogram.  Returns 
             "n_buckets": int,
             "n_values": int,
             "low": int,
             "high": int,
             "keyed": bool,
             "expires_in_version": basestring,
             "kind": basestring,
             "description": basestring,
-            "cpp_guard": basestring,
             "releaseChannelCollection": basestring,
         }
 
         # For list fields we check the items types.
         type_checked_list_fields = {
             "bug_numbers": int,
             "alert_emails": basestring,
             "labels": basestring,
             "record_in_processes": basestring,
             "keys": basestring,
             "products": basestring,
+            "operating_systems": basestring,
         }
 
         # For the server-side, where _strict_type_checks==False, we want to
         # skip the stricter type checks for these fields for dealing with
         # historical data.
         coerce_fields = ["low", "high", "n_values", "n_buckets"]
         if not self._strict_type_checks:
             # This handles some old non-numeric expressions.
--- a/toolkit/components/telemetry/shared_telemetry_utils.py
+++ b/toolkit/components/telemetry/shared_telemetry_utils.py
@@ -25,16 +25,47 @@ KNOWN_PROCESS_FLAGS = {
 
 SUPPORTED_PRODUCTS = {
     'firefox': 'Firefox',
     'fennec': 'Fennec',
     'geckoview': 'Geckoview',
     'all': 'All',
 }
 
+SUPPORTED_OPERATING_SYSTEMS = [
+    'mac',
+    'linux',
+    'windows',
+    'android',
+    'unix',
+    'all',
+]
+
+# mozinfo identifies linux, BSD variants, Solaris and SunOS as unix
+# Solaris and SunOS are identified as "unix" OS.
+UNIX_LIKE_OS = [
+    "unix",
+    "linux",
+    "bsd",
+]
+
+CANONICAL_OPERATING_SYSTEMS = {
+    'darwin': 'mac',
+    'linux': 'linux',
+    'winnt': 'windows',
+    'android': 'android',
+    # for simplicity we treat all BSD and Solaris systems as unix
+    'gnu/kfreebsd': 'unix',
+    'sunos': 'unix',
+    'dragonfly': 'unix',
+    'freeunix': 'unix',
+    'netunix': 'unix',
+    'openunix': 'unix'
+}
+
 PROCESS_ENUM_PREFIX = "mozilla::Telemetry::Common::RecordedProcessType::"
 PRODUCT_ENUM_PREFIX = "mozilla::Telemetry::Common::SupportedProduct::"
 
 
 class ParserError(Exception):
     """Thrown by different probe parsers. Errors are partitioned into
     'immediately fatal' and 'eventually fatal' so that the parser can print
     multiple error messages at a time. See bug 1401612 ."""
@@ -70,16 +101,26 @@ def is_valid_process_name(name):
 def process_name_to_enum(name):
     return PROCESS_ENUM_PREFIX + KNOWN_PROCESS_FLAGS.get(name)
 
 
 def is_valid_product(name):
     return (name in SUPPORTED_PRODUCTS)
 
 
+def is_valid_os(name):
+    return (name in SUPPORTED_OPERATING_SYSTEMS)
+
+
+def canonical_os(os):
+    """Translate possible OS_TARGET names to their canonical value."""
+
+    return CANONICAL_OPERATING_SYSTEMS.get(os.lower()) or "unknown"
+
+
 def product_name_to_enum(product):
     return PRODUCT_ENUM_PREFIX + SUPPORTED_PRODUCTS.get(product)
 
 
 class StringTable:
     """Manages a string table and allows C style serialization to a file."""
 
     def __init__(self):
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryHistograms.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryHistograms.js
@@ -1192,8 +1192,47 @@ async function test_clearHistogramsOnSna
   Assert.equal(snapshot[COUNT].sum, 42);
 
   // Finally, no data should be in the snapshot.
   Assert.equal(h.snapshot().sum, 0);
   snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
                                               false /* clear */).parent;
   Assert.ok(!(COUNT in snapshot));
 });
+
+add_task(async function test_valid_os_smoketest() {
+  let nonExistingProbe;
+  let existingProbe;
+
+  switch (AppConstants.platform) {
+    case "linux":
+      nonExistingProbe = "TELEMETRY_TEST_OS_ANDROID_ONLY";
+      existingProbe = "TELEMETRY_TEST_OS_LINUX_ONLY";
+      break;
+    case "macosx":
+      nonExistingProbe = "TELEMETRY_TEST_OS_ANDROID_ONLY";
+      existingProbe = "TELEMETRY_TEST_OS_MAC_ONLY";
+      break;
+    case "win":
+      nonExistingProbe = "TELEMETRY_TEST_OS_ANDROID_ONLY";
+      existingProbe = "TELEMETRY_TEST_OS_WIN_ONLY";
+      break;
+    case "android":
+      nonExistingProbe = "TELEMETRY_TEST_OS_LINUX_ONLY";
+      existingProbe = "TELEMETRY_TEST_OS_ANDROID_ONLY";
+      break;
+    default:
+      /* Unknown OS. Let's not test OS-specific probes */
+      return;
+  }
+
+  Assert.throws(() => Telemetry.getHistogramById(nonExistingProbe),
+    /NS_ERROR_FAILURE/,
+    `Should throw on ${nonExistingProbe} probe that's not available on ${AppConstants.platform}`);
+
+  let h = Telemetry.getHistogramById(existingProbe);
+  h.clear();
+  h.add(1);
+  let snapshot = Telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
+                                              false /* clear */).parent;
+  Assert.ok(existingProbe in snapshot, `${existingProbe} should be recorded on ${AppConstants.platform}`);
+  Assert.equal(snapshot[existingProbe].sum, 1);
+});