summaryrefslogtreecommitdiffstats
path: root/toolkit/components/telemetry/core/Telemetry.h
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/telemetry/core/Telemetry.h')
-rw-r--r--toolkit/components/telemetry/core/Telemetry.h577
1 files changed, 577 insertions, 0 deletions
diff --git a/toolkit/components/telemetry/core/Telemetry.h b/toolkit/components/telemetry/core/Telemetry.h
new file mode 100644
index 0000000000..d0fb76a24e
--- /dev/null
+++ b/toolkit/components/telemetry/core/Telemetry.h
@@ -0,0 +1,577 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* 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/. */
+
+#ifndef Telemetry_h__
+#define Telemetry_h__
+
+#include "mozilla/Maybe.h"
+#include "mozilla/TelemetryEventEnums.h"
+#include "mozilla/TelemetryHistogramEnums.h"
+#include "mozilla/TelemetryScalarEnums.h"
+#include "mozilla/TimeStamp.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsXULAppAPI.h"
+
+/******************************************************************************
+ * This implements the Telemetry system.
+ * It allows recording into histograms as well some more specialized data
+ * points and gives access to the data.
+ *
+ * For documentation on how to add and use new Telemetry probes, see:
+ * https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/start/adding-a-new-probe.html
+ *
+ * For more general information on Telemetry see:
+ * https://wiki.mozilla.org/Telemetry
+ *****************************************************************************/
+
+namespace mozilla {
+namespace Telemetry {
+
+struct HistogramAccumulation;
+struct KeyedHistogramAccumulation;
+struct ScalarAction;
+struct KeyedScalarAction;
+struct ChildEventData;
+
+struct EventExtraEntry {
+ nsCString key;
+ nsCString value;
+};
+
+/**
+ * Initialize the Telemetry service on the main thread at startup.
+ */
+void Init();
+
+/**
+ * Shutdown the Telemetry service.
+ */
+void ShutdownTelemetry();
+
+/**
+ * Adds sample to a histogram defined in TelemetryHistogramEnums.h
+ *
+ * @param id - histogram id
+ * @param sample - value to record.
+ */
+void Accumulate(HistogramID id, uint32_t sample);
+
+/**
+ * Adds an array of samples to a histogram defined in TelemetryHistograms.h
+ * @param id - histogram id
+ * @param samples - values to record.
+ */
+void Accumulate(HistogramID id, const nsTArray<uint32_t>& samples);
+
+/**
+ * Adds sample to a keyed histogram defined in TelemetryHistogramEnums.h
+ *
+ * @param id - keyed histogram id
+ * @param key - the string key
+ * @param sample - (optional) value to record, defaults to 1.
+ */
+void Accumulate(HistogramID id, const nsCString& key, uint32_t sample = 1);
+
+/**
+ * Adds an array of samples to a histogram defined in TelemetryHistograms.h
+ * @param id - histogram id
+ * @param samples - values to record.
+ * @param key - the string key
+ */
+void Accumulate(HistogramID id, const nsCString& key,
+ const nsTArray<uint32_t>& samples);
+
+/**
+ * Adds a sample to a histogram defined in TelemetryHistogramEnums.h.
+ * This function is here to support telemetry measurements from Java,
+ * where we have only names and not numeric IDs. You should almost
+ * certainly be using the by-enum-id version instead of this one.
+ *
+ * @param name - histogram name
+ * @param sample - value to record
+ */
+void Accumulate(const char* name, uint32_t sample);
+
+/**
+ * Adds a sample to a histogram defined in TelemetryHistogramEnums.h.
+ * This function is here to support telemetry measurements from Java,
+ * where we have only names and not numeric IDs. You should almost
+ * certainly be using the by-enum-id version instead of this one.
+ *
+ * @param name - histogram name
+ * @param key - the string key
+ * @param sample - sample - (optional) value to record, defaults to 1.
+ */
+void Accumulate(const char* name, const nsCString& key, uint32_t sample = 1);
+
+/**
+ * Adds sample to a categorical histogram defined in TelemetryHistogramEnums.h
+ * This is the typesafe - and preferred - way to use the categorical histograms
+ * by passing values from the corresponding Telemetry::LABELS_* enum.
+ *
+ * @param enumValue - Label value from one of the Telemetry::LABELS_* enums.
+ */
+template <class E>
+void AccumulateCategorical(E enumValue) {
+ static_assert(IsCategoricalLabelEnum<E>::value,
+ "Only categorical label enum types are supported.");
+ Accumulate(static_cast<HistogramID>(CategoricalLabelId<E>::value),
+ static_cast<uint32_t>(enumValue));
+};
+
+/**
+ * Adds an array of samples to categorical histograms defined in
+ * TelemetryHistogramEnums.h This is the typesafe - and preferred - way to use
+ * the categorical histograms by passing values from the corresponding
+ * Telemetry::LABELS_* enums.
+ *
+ * @param enumValues - Array of labels from Telemetry::LABELS_* enums.
+ */
+template <class E>
+void AccumulateCategorical(const nsTArray<E>& enumValues) {
+ static_assert(IsCategoricalLabelEnum<E>::value,
+ "Only categorical label enum types are supported.");
+ nsTArray<uint32_t> intSamples(enumValues.Length());
+
+ for (E aValue : enumValues) {
+ intSamples.AppendElement(static_cast<uint32_t>(aValue));
+ }
+
+ HistogramID categoricalId =
+ static_cast<HistogramID>(CategoricalLabelId<E>::value);
+
+ Accumulate(categoricalId, intSamples);
+}
+
+/**
+ * Adds sample to a keyed categorical histogram defined in
+ * TelemetryHistogramEnums.h This is the typesafe - and preferred - way to use
+ * the keyed categorical histograms by passing values from the corresponding
+ * Telemetry::LABELS_* enum.
+ *
+ * @param key - the string key
+ * @param enumValue - Label value from one of the Telemetry::LABELS_* enums.
+ */
+template <class E>
+void AccumulateCategoricalKeyed(const nsCString& key, E enumValue) {
+ static_assert(IsCategoricalLabelEnum<E>::value,
+ "Only categorical label enum types are supported.");
+ Accumulate(static_cast<HistogramID>(CategoricalLabelId<E>::value), key,
+ static_cast<uint32_t>(enumValue));
+};
+
+/**
+ * Adds an array of samples to a keyed categorical histogram defined in
+ * TelemetryHistogramEnums.h. This is the typesafe - and preferred - way to use
+ * the keyed categorical histograms by passing values from the corresponding
+ * Telemetry::LABELS_*enum.
+ *
+ * @param key - the string key
+ * @param enumValue - Label value from one of the Telemetry::LABELS_* enums.
+ */
+template <class E>
+void AccumulateCategoricalKeyed(const nsCString& key,
+ const nsTArray<E>& enumValues) {
+ static_assert(IsCategoricalLabelEnum<E>::value,
+ "Only categorical label enum types are supported.");
+ nsTArray<uint32_t> intSamples(enumValues.Length());
+
+ for (E aValue : enumValues) {
+ intSamples.AppendElement(static_cast<uint32_t>(aValue));
+ }
+
+ Accumulate(static_cast<HistogramID>(CategoricalLabelId<E>::value), key,
+ intSamples);
+};
+
+/**
+ * Adds sample to a categorical histogram defined in TelemetryHistogramEnums.h
+ * This string will be matched against the labels defined in Histograms.json.
+ * If the string does not match a label defined for the histogram, nothing will
+ * be recorded.
+ *
+ * @param id - The histogram id.
+ * @param label - A string label value that is defined in Histograms.json for
+ * this histogram.
+ */
+void AccumulateCategorical(HistogramID id, const nsCString& label);
+
+/**
+ * Adds an array of samples to a categorical histogram defined in
+ * Histograms.json
+ *
+ * @param id - The histogram id
+ * @param labels - The array of labels to accumulate
+ */
+void AccumulateCategorical(HistogramID id, const nsTArray<nsCString>& labels);
+
+/**
+ * Adds time delta in milliseconds to a histogram defined in
+ * TelemetryHistogramEnums.h
+ *
+ * @param id - histogram id
+ * @param start - start time
+ * @param end - end time
+ */
+void AccumulateTimeDelta(HistogramID id, TimeStamp start,
+ TimeStamp end = TimeStamp::Now());
+
+/**
+ * Adds time delta in milliseconds to a keyed histogram defined in
+ * TelemetryHistogramEnums.h
+ *
+ * @param id - histogram id
+ * @param key - the string key
+ * @param start - start time
+ * @param end - end time
+ */
+void AccumulateTimeDelta(HistogramID id, const nsCString& key, TimeStamp start,
+ TimeStamp end = TimeStamp::Now());
+
+/**
+ * Enable/disable recording for this histogram in this process at runtime.
+ * Recording is enabled by default, unless listed at
+ * kRecordingInitiallyDisabledIDs[]. id must be a valid telemetry enum,
+ *
+ * @param id - histogram id
+ * @param enabled - whether or not to enable recording from now on.
+ */
+void SetHistogramRecordingEnabled(HistogramID id, bool enabled);
+
+const char* GetHistogramName(HistogramID id);
+
+class MOZ_RAII RuntimeAutoTimer {
+ public:
+ explicit RuntimeAutoTimer(Telemetry::HistogramID aId,
+ TimeStamp aStart = TimeStamp::Now())
+ : id(aId), start(aStart) {}
+ explicit RuntimeAutoTimer(Telemetry::HistogramID aId, const nsCString& aKey,
+ TimeStamp aStart = TimeStamp::Now())
+ : id(aId), key(aKey), start(aStart) {
+ MOZ_ASSERT(!aKey.IsEmpty(), "The key must not be empty.");
+ }
+
+ ~RuntimeAutoTimer() {
+ if (key.IsEmpty()) {
+ AccumulateTimeDelta(id, start);
+ } else {
+ AccumulateTimeDelta(id, key, start);
+ }
+ }
+
+ private:
+ Telemetry::HistogramID id;
+ const nsCString key;
+ const TimeStamp start;
+};
+
+template <HistogramID id>
+class MOZ_RAII AutoTimer {
+ public:
+ explicit AutoTimer(TimeStamp aStart = TimeStamp::Now()) : start(aStart) {}
+
+ explicit AutoTimer(const nsCString& aKey, TimeStamp aStart = TimeStamp::Now())
+ : start(aStart), key(aKey) {
+ MOZ_ASSERT(!aKey.IsEmpty(), "The key must not be empty.");
+ }
+
+ ~AutoTimer() {
+ if (key.IsEmpty()) {
+ AccumulateTimeDelta(id, start);
+ } else {
+ AccumulateTimeDelta(id, key, start);
+ }
+ }
+
+ private:
+ const TimeStamp start;
+ const nsCString key;
+};
+
+class MOZ_RAII RuntimeAutoCounter {
+ public:
+ explicit RuntimeAutoCounter(HistogramID aId, uint32_t counterStart = 0)
+ : id(aId), counter(counterStart) {}
+
+ ~RuntimeAutoCounter() { Accumulate(id, counter); }
+
+ // Prefix increment only, to encourage good habits.
+ void operator++() {
+ if (NS_WARN_IF(counter == std::numeric_limits<uint32_t>::max())) {
+ return;
+ }
+ ++counter;
+ }
+
+ // Chaining doesn't make any sense, don't return anything.
+ void operator+=(int increment) {
+ if (NS_WARN_IF(increment > 0 &&
+ static_cast<uint32_t>(increment) >
+ (std::numeric_limits<uint32_t>::max() - counter))) {
+ counter = std::numeric_limits<uint32_t>::max();
+ return;
+ }
+ if (NS_WARN_IF(increment < 0 &&
+ static_cast<uint32_t>(-increment) > counter)) {
+ counter = std::numeric_limits<uint32_t>::min();
+ return;
+ }
+ counter += increment;
+ }
+
+ private:
+ HistogramID id;
+ uint32_t counter;
+};
+
+template <HistogramID id>
+class MOZ_RAII AutoCounter {
+ public:
+ explicit AutoCounter(uint32_t counterStart = 0) : counter(counterStart) {}
+
+ ~AutoCounter() { Accumulate(id, counter); }
+
+ // Prefix increment only, to encourage good habits.
+ void operator++() {
+ if (NS_WARN_IF(counter == std::numeric_limits<uint32_t>::max())) {
+ return;
+ }
+ ++counter;
+ }
+
+ // Chaining doesn't make any sense, don't return anything.
+ void operator+=(int increment) {
+ if (NS_WARN_IF(increment > 0 &&
+ static_cast<uint32_t>(increment) >
+ (std::numeric_limits<uint32_t>::max() - counter))) {
+ counter = std::numeric_limits<uint32_t>::max();
+ return;
+ }
+ if (NS_WARN_IF(increment < 0 &&
+ static_cast<uint32_t>(-increment) > counter)) {
+ counter = std::numeric_limits<uint32_t>::min();
+ return;
+ }
+ counter += increment;
+ }
+
+ private:
+ uint32_t counter;
+};
+
+/**
+ * Indicates whether Telemetry base data recording is turned on. Added for
+ * future uses.
+ */
+bool CanRecordBase();
+
+/**
+ * Indicates whether Telemetry extended data recording is turned on. This is
+ * intended to guard calls to Accumulate when the statistic being recorded is
+ * expensive to compute.
+ */
+bool CanRecordExtended();
+
+/**
+ * Indicates whether Telemetry release data recording is turned on. Usually
+ * true.
+ *
+ * @see nsITelemetry.canRecordReleaseData
+ */
+bool CanRecordReleaseData();
+
+/**
+ * Indicates whether Telemetry pre-release data recording is turned on. Tends
+ * to be true on pre-release channels.
+ *
+ * @see nsITelemetry.canRecordPrereleaseData
+ */
+bool CanRecordPrereleaseData();
+
+/**
+ * Records slow SQL statements for Telemetry reporting.
+ *
+ * @param statement - offending SQL statement to record
+ * @param dbName - DB filename
+ * @param delay - execution time in milliseconds
+ */
+void RecordSlowSQLStatement(const nsACString& statement,
+ const nsACString& dbName, uint32_t delay);
+
+/**
+ * Initialize I/O Reporting
+ * Initially this only records I/O for files in the binary directory.
+ *
+ * @param aXreDir - XRE directory
+ */
+void InitIOReporting(nsIFile* aXreDir);
+
+/**
+ * Set the profile directory. Once called, files in the profile directory will
+ * be included in I/O reporting. We can't use the directory
+ * service to obtain this information because it isn't running yet.
+ */
+void SetProfileDir(nsIFile* aProfD);
+
+/**
+ * Called to inform Telemetry that startup has completed.
+ */
+void LeavingStartupStage();
+
+/**
+ * Called to inform Telemetry that shutdown is commencing.
+ */
+void EnteringShutdownStage();
+
+/**
+ * Thresholds for a statement to be considered slow, in milliseconds
+ */
+const uint32_t kSlowSQLThresholdForMainThread = 50;
+const uint32_t kSlowSQLThresholdForHelperThreads = 100;
+
+/**
+ * Record a failed attempt at locking the user's profile.
+ *
+ * @param aProfileDir The profile directory whose lock attempt failed
+ */
+void WriteFailedProfileLock(nsIFile* aProfileDir);
+
+/**
+ * Adds the value to the given scalar.
+ *
+ * @param aId The scalar enum id.
+ * @param aValue The value to add to the scalar.
+ */
+void ScalarAdd(mozilla::Telemetry::ScalarID aId, uint32_t aValue);
+
+/**
+ * Sets the scalar to the given value.
+ *
+ * @param aId The scalar enum id.
+ * @param aValue The value to set the scalar to.
+ */
+void ScalarSet(mozilla::Telemetry::ScalarID aId, uint32_t aValue);
+
+/**
+ * Sets the scalar to the given value.
+ *
+ * @param aId The scalar enum id.
+ * @param aValue The value to set the scalar to.
+ */
+void ScalarSet(mozilla::Telemetry::ScalarID aId, bool aValue);
+
+/**
+ * Sets the scalar to the given value.
+ *
+ * @param aId The scalar enum id.
+ * @param aValue The value to set the scalar to, truncated to
+ * 50 characters if exceeding that length.
+ */
+void ScalarSet(mozilla::Telemetry::ScalarID aId, const nsAString& aValue);
+
+/**
+ * Sets the scalar to the maximum of the current and the passed value.
+ *
+ * @param aId The scalar enum id.
+ * @param aValue The value the scalar is set to if its greater
+ * than the current value.
+ */
+void ScalarSetMaximum(mozilla::Telemetry::ScalarID aId, uint32_t aValue);
+
+/**
+ * Adds the value to the given scalar.
+ *
+ * @param aId The scalar enum id.
+ * @param aKey The scalar key.
+ * @param aValue The value to add to the scalar.
+ */
+void ScalarAdd(mozilla::Telemetry::ScalarID aId, const nsAString& aKey,
+ uint32_t aValue);
+
+/**
+ * Sets the scalar to the given value.
+ *
+ * @param aId The scalar enum id.
+ * @param aKey The scalar key.
+ * @param aValue The value to set the scalar to.
+ */
+void ScalarSet(mozilla::Telemetry::ScalarID aId, const nsAString& aKey,
+ uint32_t aValue);
+
+/**
+ * Sets the scalar to the given value.
+ *
+ * @param aId The scalar enum id.
+ * @param aKey The scalar key.
+ * @param aValue The value to set the scalar to.
+ */
+void ScalarSet(mozilla::Telemetry::ScalarID aId, const nsAString& aKey,
+ bool aValue);
+
+/**
+ * Sets the scalar to the maximum of the current and the passed value.
+ *
+ * @param aId The scalar enum id.
+ * @param aKey The scalar key.
+ * @param aValue The value the scalar is set to if its greater
+ * than the current value.
+ */
+void ScalarSetMaximum(mozilla::Telemetry::ScalarID aId, const nsAString& aKey,
+ uint32_t aValue);
+
+template <ScalarID id>
+class MOZ_RAII AutoScalarTimer {
+ public:
+ explicit AutoScalarTimer(TimeStamp aStart = TimeStamp::Now())
+ : start(aStart) {}
+
+ explicit AutoScalarTimer(const nsAString& aKey,
+ TimeStamp aStart = TimeStamp::Now())
+ : start(aStart), key(aKey) {
+ MOZ_ASSERT(!aKey.IsEmpty(), "The key must not be empty.");
+ }
+
+ ~AutoScalarTimer() {
+ TimeStamp end = TimeStamp::Now();
+ uint32_t delta = static_cast<uint32_t>((end - start).ToMilliseconds());
+ if (key.IsEmpty()) {
+ mozilla::Telemetry::ScalarSet(id, delta);
+ } else {
+ mozilla::Telemetry::ScalarSet(id, key, delta);
+ }
+ }
+
+ private:
+ const TimeStamp start;
+ const nsString key;
+};
+
+/**
+ * Records an event. See the Event documentation for more information:
+ * https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html
+ *
+ * @param aId The event enum id.
+ * @param aValue Optional. The event value.
+ * @param aExtra Optional. The event's extra key/value pairs.
+ */
+void RecordEvent(mozilla::Telemetry::EventID aId,
+ const mozilla::Maybe<nsCString>& aValue,
+ const mozilla::Maybe<CopyableTArray<EventExtraEntry>>& aExtra);
+
+/**
+ * Enables recording of events in a category.
+ * Events default to recording disabled.
+ * This toggles recording for all events in the specified category.
+ *
+ * @param aCategory The category name.
+ * @param aEnabled Whether recording should be enabled or disabled.
+ */
+void SetEventRecordingEnabled(const nsACString& aCategory, bool aEnabled);
+
+} // namespace Telemetry
+} // namespace mozilla
+
+#endif // Telemetry_h__