--- a/browser/modules/test/browser_UsageTelemetry_content.js
+++ b/browser/modules/test/browser_UsageTelemetry_content.js
@@ -76,18 +76,17 @@ add_task(function* test_context_menu() {
Assert.equal(Object.keys(scalars[SCALAR_CONTEXT_MENU]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, "other-MozSearch.contextmenu", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "contextmenu", null, {engine: "other-MozSearch"}]]);
contextMenu.hidePopup();
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_about_newtab() {
@@ -113,14 +112,13 @@ add_task(function* test_about_newtab() {
Assert.equal(Object.keys(scalars[SCALAR_ABOUT_NEWTAB]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, "other-MozSearch.newtab", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "about_newtab", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
--- a/browser/modules/test/browser_UsageTelemetry_content_aboutHome.js
+++ b/browser/modules/test/browser_UsageTelemetry_content_aboutHome.js
@@ -76,14 +76,13 @@ add_task(function* test_abouthome_simple
Assert.equal(Object.keys(scalars[SCALAR_ABOUT_HOME]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, "other-MozSearch.abouthome", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "about_home", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
--- a/browser/modules/test/browser_UsageTelemetry_searchbar.js
+++ b/browser/modules/test/browser_UsageTelemetry_searchbar.js
@@ -102,18 +102,17 @@ add_task(function* test_plainQuery() {
Assert.equal(Object.keys(scalars[SCALAR_SEARCHBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, "other-MozSearch.searchbar", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "enter", {engine: "other-MozSearch"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_oneOff() {
// Let's reset the counts.
Services.telemetry.clearScalars();
@@ -137,18 +136,17 @@ add_task(function* test_oneOff() {
Assert.equal(Object.keys(scalars[SCALAR_SEARCHBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, "other-MozSearch2.searchbar", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "oneoff", {engine: "other-MozSearch2"}]]);
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_suggestion() {
// Let's reset the counts.
Services.telemetry.clearScalars();
@@ -184,16 +182,15 @@ add_task(function* test_suggestion() {
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
let searchEngineId = "other-" + suggestionEngine.name;
checkKeyedHistogram(search_hist, searchEngineId + ".searchbar", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "searchbar", "suggestion", {engine: searchEngineId}]]);
Services.search.currentEngine = previousEngine;
Services.search.removeEngine(suggestionEngine);
yield BrowserTestUtils.removeTab(tab);
});
--- a/browser/modules/test/browser_UsageTelemetry_urlbar.js
+++ b/browser/modules/test/browser_UsageTelemetry_urlbar.js
@@ -121,18 +121,17 @@ add_task(function* test_simpleQuery() {
Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "enter", {engine: "other-MozSearch"}]]);
// Check the histograms as well.
let resultIndexes = resultIndexHist.snapshot();
checkHistogramResults(resultIndexes, 0, "FX_URLBAR_SELECTED_RESULT_INDEX");
let resultTypes = resultTypeHist.snapshot();
checkHistogramResults(resultTypes,
@@ -167,18 +166,17 @@ add_task(function* test_searchAlias() {
Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "alias", {engine: "other-MozSearch"}]]);
// Check the histograms as well.
let resultIndexes = resultIndexHist.snapshot();
checkHistogramResults(resultIndexes, 0, "FX_URLBAR_SELECTED_RESULT_INDEX");
let resultTypes = resultTypeHist.snapshot();
checkHistogramResults(resultTypes,
@@ -216,18 +214,17 @@ add_task(function* test_oneOff() {
Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "oneoff", {engine: "other-MozSearch"}]]);
// Check the histograms as well.
let resultIndexes = resultIndexHist.snapshot();
checkHistogramResults(resultIndexes, 0, "FX_URLBAR_SELECTED_RESULT_INDEX");
let resultTypes = resultTypeHist.snapshot();
checkHistogramResults(resultTypes,
@@ -277,18 +274,17 @@ add_task(function* test_suggestion() {
"This search must only increment one entry in the scalar.");
// Make sure SEARCH_COUNTS contains identical values.
let searchEngineId = "other-" + suggestionEngine.name;
checkKeyedHistogram(search_hist, searchEngineId + ".urlbar", 1);
// Also check events.
let events = Services.telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- Assert.ok("default" in events, "We should have recorded events in the parent process.");
- events = events.default.filter(e => e[1] == "navigation" && e[2] == "search");
+ events = events.filter(e => e[1] == "navigation" && e[2] == "search");
checkEvents(events, [["navigation", "search", "urlbar", "suggestion", {engine: searchEngineId}]]);
// Check the histograms as well.
let resultIndexes = resultIndexHist.snapshot();
checkHistogramResults(resultIndexes, 3, "FX_URLBAR_SELECTED_RESULT_INDEX");
let resultTypes = resultTypeHist.snapshot();
checkHistogramResults(resultTypes,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5073,23 +5073,16 @@ ContentParent::RecvUpdateChildScalars(
mozilla::ipc::IPCResult
ContentParent::RecvUpdateChildKeyedScalars(
InfallibleTArray<KeyedScalarAction>&& aScalarActions)
{
TelemetryIPC::UpdateChildKeyedScalars(GeckoProcessType_Content, aScalarActions);
return IPC_OK();
}
-mozilla::ipc::IPCResult
-ContentParent::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents)
-{
- TelemetryIPC::RecordChildEvents(GeckoProcessType_Content, aEvents);
- return IPC_OK();
-}
-
PURLClassifierParent*
ContentParent::AllocPURLClassifierParent(const Principal& aPrincipal,
const bool& aUseTrackingProtection,
bool* aSuccess)
{
MOZ_ASSERT(NS_IsMainThread());
*aSuccess = true;
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1117,18 +1117,16 @@ private:
virtual mozilla::ipc::IPCResult RecvAccumulateChildHistograms(
InfallibleTArray<Accumulation>&& aAccumulations) override;
virtual mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(
InfallibleTArray<KeyedAccumulation>&& aAccumulations) override;
virtual mozilla::ipc::IPCResult RecvUpdateChildScalars(
InfallibleTArray<ScalarAction>&& aScalarActions) override;
virtual mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars(
InfallibleTArray<KeyedScalarAction>&& aScalarActions) override;
- virtual mozilla::ipc::IPCResult RecvRecordChildEvents(
- nsTArray<ChildEventData>&& events) override;
public:
void SendGetFilesResponseAndForget(const nsID& aID,
const GetFilesResponseResult& aResult);
bool SendRequestMemoryReport(const uint32_t& aGeneration,
const bool& aAnonymize,
const bool& aMinimizeMemoryUsage,
const MaybeFileDesc& aDMDFile) override;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -85,17 +85,16 @@ using class mozilla::dom::ipc::Structure
using mozilla::DataStorageType from "ipc/DataStorageIPCUtils.h";
using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
using struct mozilla::dom::FlyWebPublishOptions from "mozilla/dom/FlyWebPublishOptionsIPCSerializer.h";
using mozilla::Telemetry::Accumulation from "mozilla/TelemetryComms.h";
using mozilla::Telemetry::KeyedAccumulation from "mozilla/TelemetryComms.h";
using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
-using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
union ChromeRegistryItem
{
ChromePackage;
OverrideMapping;
SubstitutionMapping;
};
@@ -1194,17 +1193,16 @@ parent:
/**
* Messages for communicating child Telemetry to the parent process
*/
async AccumulateChildHistograms(Accumulation[] accumulations);
async AccumulateChildKeyedHistograms(KeyedAccumulation[] accumulations);
async UpdateChildScalars(ScalarAction[] updates);
async UpdateChildKeyedScalars(KeyedScalarAction[] updates);
- async RecordChildEvents(ChildEventData[] events);
sync GetA11yContentId() returns (uint32_t aContentId);
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);
both:
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -168,23 +168,16 @@ GPUChild::RecvUpdateChildScalars(Infalli
mozilla::ipc::IPCResult
GPUChild::RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions)
{
TelemetryIPC::UpdateChildKeyedScalars(GeckoProcessType_GPU, aScalarActions);
return IPC_OK();
}
mozilla::ipc::IPCResult
-GPUChild::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents)
-{
- TelemetryIPC::RecordChildEvents(GeckoProcessType_GPU, aEvents);
- return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
GPUChild::RecvNotifyDeviceReset()
{
mHost->mListener->OnProcessDeviceReset(mHost);
return IPC_OK();
}
bool
GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
--- a/gfx/ipc/GPUChild.h
+++ b/gfx/ipc/GPUChild.h
@@ -38,23 +38,20 @@ public:
// gfxVarReceiver overrides.
void OnVarChanged(const GfxVarUpdate& aVar) override;
// PGPUChild overrides.
mozilla::ipc::IPCResult RecvInitComplete(const GPUDeviceData& aData) override;
mozilla::ipc::IPCResult RecvReportCheckerboard(const uint32_t& aSeverity, const nsCString& aLog) override;
mozilla::ipc::IPCResult RecvInitCrashReporter(Shmem&& shmem, const NativeThreadId& aThreadId) override;
-
mozilla::ipc::IPCResult RecvAccumulateChildHistograms(InfallibleTArray<Accumulation>&& aAccumulations) override;
mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(InfallibleTArray<KeyedAccumulation>&& aAccumulations) override;
mozilla::ipc::IPCResult RecvUpdateChildScalars(InfallibleTArray<ScalarAction>&& aScalarActions) override;
mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions) override;
- mozilla::ipc::IPCResult RecvRecordChildEvents(nsTArray<ChildEventData>&& events) override;
-
void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvGraphicsError(const nsCString& aError) override;
mozilla::ipc::IPCResult RecvNotifyUiObservers(const nsCString& aTopic) override;
mozilla::ipc::IPCResult RecvNotifyDeviceReset() override;
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
bool SendRequestMemoryReport(const uint32_t& aGeneration,
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -17,17 +17,16 @@ using mozilla::TimeDuration from "mozill
using mozilla::CSSToLayoutDeviceScale from "Units.h";
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h";
using mozilla::Telemetry::Accumulation from "mozilla/TelemetryComms.h";
using mozilla::Telemetry::KeyedAccumulation from "mozilla/TelemetryComms.h";
using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
-using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
namespace mozilla {
namespace gfx {
union GfxPrefValue {
bool;
int32_t;
uint32_t;
@@ -110,17 +109,16 @@ child:
// observer service.
async NotifyUiObservers(nsCString aTopic);
// Messages for reporting telemetry to the UI process.
async AccumulateChildHistograms(Accumulation[] accumulations);
async AccumulateChildKeyedHistograms(KeyedAccumulation[] accumulations);
async UpdateChildScalars(ScalarAction[] actions);
async UpdateChildKeyedScalars(KeyedScalarAction[] actions);
- async RecordChildEvents(ChildEventData[] events);
async NotifyDeviceReset();
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);
};
} // namespace gfx
--- a/toolkit/components/telemetry/Telemetry.h
+++ b/toolkit/components/telemetry/Telemetry.h
@@ -33,17 +33,16 @@ namespace HangMonitor {
class HangAnnotations;
} // namespace HangMonitor
namespace Telemetry {
struct Accumulation;
struct KeyedAccumulation;
struct ScalarAction;
struct KeyedScalarAction;
-struct ChildEventData;
enum TimerResolution {
Millisecond,
Microsecond
};
/**
* Create and destroy the underlying base::StatisticsRecorder singleton.
--- a/toolkit/components/telemetry/TelemetryEvent.cpp
+++ b/toolkit/components/telemetry/TelemetryEvent.cpp
@@ -9,43 +9,38 @@
#include "nsHashKeys.h"
#include "nsDataHashtable.h"
#include "nsClassHashtable.h"
#include "nsTArray.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/Unused.h"
#include "mozilla/Maybe.h"
#include "mozilla/StaticPtr.h"
-#include "mozilla/Pair.h"
#include "jsapi.h"
#include "nsJSUtils.h"
#include "nsXULAppAPI.h"
#include "nsUTF8Utils.h"
#include "TelemetryCommon.h"
#include "TelemetryEvent.h"
#include "TelemetryEventData.h"
-#include "ipc/TelemetryIPCAccumulator.h"
using mozilla::StaticMutex;
using mozilla::StaticMutexAutoLock;
using mozilla::ArrayLength;
using mozilla::Maybe;
using mozilla::Nothing;
+using mozilla::Pair;
using mozilla::StaticAutoPtr;
using mozilla::Telemetry::Common::AutoHashtable;
using mozilla::Telemetry::Common::IsExpiredVersion;
using mozilla::Telemetry::Common::CanRecordDataset;
using mozilla::Telemetry::Common::IsInDataset;
using mozilla::Telemetry::Common::MsSinceProcessStart;
using mozilla::Telemetry::Common::LogToBrowserConsole;
-using mozilla::Telemetry::EventExtraEntry;
-using mozilla::Telemetry::ChildEventData;
-
-namespace TelemetryIPCAccumulator = mozilla::TelemetryIPCAccumulator;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
// Naming: there are two kinds of functions in this file:
//
// * Functions taking a StaticMutexAutoLock: these can only be reached via
// an interface function (TelemetryEvent::*). They expect the interface
@@ -103,17 +98,22 @@ typedef nsClassHashtable<nsCStringHashKe
enum class RecordEventResult {
Ok,
UnknownEvent,
InvalidExtraKey,
StorageLimitReached,
};
-typedef nsTArray<EventExtraEntry> ExtraArray;
+struct ExtraEntry {
+ const nsCString key;
+ const nsCString value;
+};
+
+typedef nsTArray<ExtraEntry> ExtraArray;
class EventRecord {
public:
EventRecord(double timestamp, uint32_t eventId, const Maybe<nsCString>& value,
const ExtraArray& extra)
: mTimestamp(timestamp)
, mEventId(eventId)
, mValue(value)
@@ -253,27 +253,25 @@ bool gCanRecordExtended;
StringUintMap gEventNameIDMap(kEventCount);
// The CategoryName -> CategoryID cache map.
StringUintMap gCategoryNameIDMap;
// This tracks the IDs of the categories for which recording is enabled.
nsTHashtable<nsUint32HashKey> gEnabledCategories;
-// The main event storage. Events are inserted here, keyed by process id and
-// in recording order.
-typedef nsTArray<EventRecord> EventRecordArray;
-nsClassHashtable<nsUint32HashKey, EventRecordArray> gEventRecords;
+// The main event storage. Events are inserted here in recording order.
+StaticAutoPtr<nsTArray<EventRecord>> gEventRecords;
} // namespace
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
-// PRIVATE: thread-safe helpers for event recording.
+// PRIVATE: thread-unsafe helpers for event recording.
namespace {
bool
CanRecordEvent(const StaticMutexAutoLock& lock, const CommonEventInfo& info)
{
if (!gCanRecordBase) {
return false;
@@ -281,37 +279,24 @@ CanRecordEvent(const StaticMutexAutoLock
if (!CanRecordDataset(info.dataset, gCanRecordBase, gCanRecordExtended)) {
return false;
}
return gEnabledCategories.GetEntry(info.category_offset);
}
-EventRecordArray*
-GetEventRecordsForProcess(const StaticMutexAutoLock& lock, GeckoProcessType processType)
+RecordEventResult
+RecordEvent(const StaticMutexAutoLock& lock, double timestamp,
+ const nsACString& category, const nsACString& method,
+ const nsACString& object, const Maybe<nsCString>& value,
+ const ExtraArray& extra)
{
- EventRecordArray* eventRecords = nullptr;
- if (!gEventRecords.Get(processType, &eventRecords)) {
- eventRecords = new EventRecordArray();
- gEventRecords.Put(processType, eventRecords);
- }
- return eventRecords;
-}
-
-RecordEventResult
-RecordEvent(const StaticMutexAutoLock& lock, GeckoProcessType processType,
- double timestamp, const nsACString& category,
- const nsACString& method, const nsACString& object,
- const Maybe<nsCString>& value, const ExtraArray& extra)
-{
- EventRecordArray* eventRecords = GetEventRecordsForProcess(lock, processType);
-
// Apply hard limit on event count in storage.
- if (eventRecords->Length() >= kMaxEventRecords) {
+ if (gEventRecords->Length() >= kMaxEventRecords) {
return RecordEventResult::StorageLimitReached;
}
// Look up the event id.
const nsCString& name = UniqueEventName(category, method, object);
uint32_t eventId;
if (!gEventNameIDMap.Get(name, &eventId)) {
return RecordEventResult::UnknownEvent;
@@ -339,126 +324,25 @@ RecordEvent(const StaticMutexAutoLock& l
for (uint32_t i = 0; i < extra.Length(); ++i) {
if (!validExtraKeys.GetEntry(extra[i].key)) {
return RecordEventResult::InvalidExtraKey;
}
}
// Add event record.
- eventRecords->AppendElement(EventRecord(timestamp, eventId, value, extra));
+ gEventRecords->AppendElement(EventRecord(timestamp, eventId, value, extra));
return RecordEventResult::Ok;
}
} // anonymous namespace
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
-// PRIVATE: thread-unsafe helpers for event handling.
-
-namespace {
-
-nsresult
-SerializeEventsArray(const EventRecordArray& events,
- JSContext* cx,
- JS::MutableHandleObject result)
-{
- // We serialize the events to a JS array.
- JS::RootedObject eventsArray(cx, JS_NewArrayObject(cx, events.Length()));
- if (!eventsArray) {
- return NS_ERROR_FAILURE;
- }
-
- for (uint32_t i = 0; i < events.Length(); ++i) {
- const EventRecord& record = events[i];
- const EventInfo& info = gEventInfo[record.EventId()];
-
- // Each entry is an array of one of the forms:
- // [timestamp, category, method, object, value]
- // [timestamp, category, method, object, null, extra]
- // [timestamp, category, method, object, value, extra]
- JS::AutoValueVector items(cx);
-
- // Add timestamp.
- JS::Rooted<JS::Value> val(cx);
- if (!items.append(JS::NumberValue(floor(record.Timestamp())))) {
- return NS_ERROR_FAILURE;
- }
-
- // Add category, method, object.
- const char* strings[] = {
- info.common_info.category(),
- info.method(),
- info.object(),
- };
- for (const char* s : strings) {
- const NS_ConvertUTF8toUTF16 wide(s);
- if (!items.append(JS::StringValue(JS_NewUCStringCopyN(cx, wide.Data(), wide.Length())))) {
- return NS_ERROR_FAILURE;
- }
- }
-
- // Add the optional string value only when needed.
- // When the value field is empty and extra is not set, we can save a little space that way.
- // We still need to submit a null value if extra is set, to match the form:
- // [ts, category, method, object, null, extra]
- if (record.Value()) {
- const NS_ConvertUTF8toUTF16 wide(record.Value().value());
- if (!items.append(JS::StringValue(JS_NewUCStringCopyN(cx, wide.Data(), wide.Length())))) {
- return NS_ERROR_FAILURE;
- }
- } else if (!record.Extra().IsEmpty()) {
- if (!items.append(JS::NullValue())) {
- return NS_ERROR_FAILURE;
- }
- }
-
- // Add the optional extra dictionary.
- // To save a little space, only add it when it is not empty.
- if (!record.Extra().IsEmpty()) {
- JS::RootedObject obj(cx, JS_NewPlainObject(cx));
- if (!obj) {
- return NS_ERROR_FAILURE;
- }
-
- // Add extra key & value entries.
- const ExtraArray& extra = record.Extra();
- for (uint32_t i = 0; i < extra.Length(); ++i) {
- const NS_ConvertUTF8toUTF16 wide(extra[i].value);
- JS::Rooted<JS::Value> value(cx);
- value.setString(JS_NewUCStringCopyN(cx, wide.Data(), wide.Length()));
-
- if (!JS_DefineProperty(cx, obj, extra[i].key.get(), value, JSPROP_ENUMERATE)) {
- return NS_ERROR_FAILURE;
- }
- }
- val.setObject(*obj);
-
- if (!items.append(val)) {
- return NS_ERROR_FAILURE;
- }
- }
-
- // Add the record to the events array.
- JS::RootedObject itemsArray(cx, JS_NewArrayObject(cx, items));
- if (!JS_DefineElement(cx, eventsArray, i, itemsArray, JSPROP_ENUMERATE)) {
- return NS_ERROR_FAILURE;
- }
- }
-
- result.set(eventsArray);
- return NS_OK;
-}
-
-} // anonymous namespace
-
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-//
// EXTERNALLY VISIBLE FUNCTIONS in namespace TelemetryEvents::
// This is a StaticMutex rather than a plain Mutex (1) so that
// it gets initialised in a thread-safe manner the first time
// it is used, and (2) because it is never de-initialised, and
// a normal Mutex would show up as a leak in BloatView. StaticMutex
// also has the "OffTheBooks" property, so it won't show as a leak
// in BloatView.
@@ -473,16 +357,18 @@ TelemetryEvent::InitializeGlobalState(bo
{
StaticMutexAutoLock locker(gTelemetryEventsMutex);
MOZ_ASSERT(!gInitDone, "TelemetryEvent::InitializeGlobalState "
"may only be called once");
gCanRecordBase = aCanRecordBase;
gCanRecordExtended = aCanRecordExtended;
+ gEventRecords = new nsTArray<EventRecord>();
+
// Populate the static event name->id cache. Note that the event names are
// statically allocated and come from the automatically generated TelemetryEventData.h.
const uint32_t eventCount = static_cast<uint32_t>(mozilla::Telemetry::EventID::EventCount);
for (uint32_t i = 0; i < eventCount; ++i) {
const EventInfo& info = gEventInfo[i];
uint32_t eventId = i;
// If this event is expired, mark it with a special event id.
@@ -513,17 +399,18 @@ TelemetryEvent::DeInitializeGlobalState(
MOZ_ASSERT(gInitDone);
gCanRecordBase = false;
gCanRecordExtended = false;
gEventNameIDMap.Clear();
gCategoryNameIDMap.Clear();
gEnabledCategories.Clear();
- gEventRecords.Clear();
+ gEventRecords->Clear();
+ gEventRecords = nullptr;
gInitDone = false;
}
void
TelemetryEvent::SetCanRecordBase(bool b)
{
StaticMutexAutoLock locker(gTelemetryEventsMutex);
@@ -532,34 +419,26 @@ TelemetryEvent::SetCanRecordBase(bool b)
void
TelemetryEvent::SetCanRecordExtended(bool b) {
StaticMutexAutoLock locker(gTelemetryEventsMutex);
gCanRecordExtended = b;
}
nsresult
-TelemetryEvent::RecordChildEvents(GeckoProcessType aProcessType,
- const nsTArray<mozilla::Telemetry::ChildEventData>& aEvents)
-{
- MOZ_ASSERT(XRE_IsParentProcess());
- StaticMutexAutoLock locker(gTelemetryEventsMutex);
- for (uint32_t i = 0; i < aEvents.Length(); ++i) {
- const mozilla::Telemetry::ChildEventData e = aEvents[i];
- ::RecordEvent(locker, aProcessType, e.timestamp, e.category, e.method, e.object, e.value, e.extra);
- }
- return NS_OK;
-}
-
-nsresult
TelemetryEvent::RecordEvent(const nsACString& aCategory, const nsACString& aMethod,
const nsACString& aObject, JS::HandleValue aValue,
JS::HandleValue aExtra, JSContext* cx,
uint8_t optional_argc)
{
+ // Currently only recording in the parent process is supported.
+ if (!XRE_IsParentProcess()) {
+ return NS_OK;
+ }
+
// Get the current time.
double timestamp = -1;
nsresult rv = MsSinceProcessStart(×tamp);
if (NS_FAILED(rv)) {
LogToBrowserConsole(nsIScriptError::warningFlag,
NS_LITERAL_STRING("Failed to get time since process start."));
return NS_OK;
}
@@ -632,37 +511,32 @@ TelemetryEvent::RecordEvent(const nsACSt
nsCString str = NS_ConvertUTF16toUTF8(jsStr);
if (str.Length() > kMaxExtraValueByteLength) {
LogToBrowserConsole(nsIScriptError::warningFlag,
NS_LITERAL_STRING("Extra value exceeds maximum string length, truncating."));
TruncateToByteLength(str, kMaxExtraValueByteLength);
}
- extra.AppendElement(EventExtraEntry{NS_ConvertUTF16toUTF8(key), str});
+ extra.AppendElement(ExtraEntry{NS_ConvertUTF16toUTF8(key), str});
}
}
- if (!XRE_IsParentProcess()) {
- TelemetryIPCAccumulator::RecordChildEvent(timestamp, aCategory, aMethod, aObject, value, extra);
- return NS_OK;
- }
-
// Lock for accessing internal data.
// While the lock is being held, no complex calls like JS calls can be made,
// as all of these could record Telemetry, which would result in deadlock.
RecordEventResult res;
{
StaticMutexAutoLock lock(gTelemetryEventsMutex);
if (!gInitDone) {
return NS_ERROR_FAILURE;
}
- res = ::RecordEvent(lock, GeckoProcessType_Default, timestamp, aCategory, aMethod, aObject, value, extra);
+ res = ::RecordEvent(lock, timestamp, aCategory, aMethod, aObject, value, extra);
}
// Trigger warnings or errors where needed.
switch (res) {
case RecordEventResult::UnknownEvent: {
JS_ReportErrorASCII(cx, R"(Unknown event: ["%s", "%s", "%s"])",
PromiseFlatCString(aCategory).get(),
PromiseFlatCString(aMethod).get(),
@@ -681,96 +555,138 @@ TelemetryEvent::RecordEvent(const nsACSt
return NS_OK;
}
}
nsresult
TelemetryEvent::CreateSnapshots(uint32_t aDataset, bool aClear, JSContext* cx,
uint8_t optional_argc, JS::MutableHandleValue aResult)
{
- if (!XRE_IsParentProcess()) {
- return NS_ERROR_FAILURE;
- }
-
- // Creating a JS snapshot of the events is a two-step process:
- // (1) Lock the storage and copy the events into function-local storage.
- // (2) Serialize the events into JS.
- // We can't hold a lock for (2) because we will run into deadlocks otherwise
- // from JS recording Telemetry.
-
- // (1) Extract the events from storage with a lock held.
- nsTArray<mozilla::Pair<const char*, EventRecordArray>> processEvents;
+ // Extract the events from storage.
+ nsTArray<EventRecord> events;
{
StaticMutexAutoLock locker(gTelemetryEventsMutex);
if (!gInitDone) {
return NS_ERROR_FAILURE;
}
- for (auto iter = gEventRecords.Iter(); !iter.Done(); iter.Next()) {
- const EventRecordArray* eventStorage = static_cast<EventRecordArray*>(iter.Data());
- EventRecordArray events;
-
- const uint32_t len = eventStorage->Length();
- for (uint32_t i = 0; i < len; ++i) {
- const EventRecord& record = (*eventStorage)[i];
- const EventInfo& info = gEventInfo[record.EventId()];
+ uint32_t len = gEventRecords->Length();
+ for (uint32_t i = 0; i < len; ++i) {
+ const EventRecord& record = (*gEventRecords)[i];
+ const EventInfo& info = gEventInfo[record.EventId()];
- if (IsInDataset(info.common_info.dataset, aDataset)) {
- events.AppendElement(record);
- }
- }
-
- if (events.Length()) {
- const char* processName = XRE_ChildProcessTypeToString(GeckoProcessType(iter.Key()));
- processEvents.AppendElement(mozilla::MakePair(processName, events));
+ if (IsInDataset(info.common_info.dataset, aDataset)) {
+ events.AppendElement(record);
}
}
if (aClear) {
- gEventRecords.Clear();
+ gEventRecords->Clear();
}
}
- // (2) Serialize the events to a JS object.
- JS::RootedObject rootObj(cx, JS_NewPlainObject(cx));
- if (!rootObj) {
+ // We serialize the events to a JS array.
+ JS::RootedObject eventsArray(cx, JS_NewArrayObject(cx, events.Length()));
+ if (!eventsArray) {
return NS_ERROR_FAILURE;
}
- const uint32_t processLength = processEvents.Length();
- for (uint32_t i = 0; i < processLength; ++i)
- {
- JS::RootedObject eventsArray(cx);
- if (NS_FAILED(SerializeEventsArray(processEvents[i].second(), cx, &eventsArray))) {
+ for (uint32_t i = 0; i < events.Length(); ++i) {
+ const EventRecord& record = events[i];
+ const EventInfo& info = gEventInfo[record.EventId()];
+
+ // Each entry is an array of one of the forms:
+ // [timestamp, category, method, object, value]
+ // [timestamp, category, method, object, null, extra]
+ // [timestamp, category, method, object, value, extra]
+ JS::AutoValueVector items(cx);
+
+ // Add timestamp.
+ JS::Rooted<JS::Value> val(cx);
+ if (!items.append(JS::NumberValue(floor(record.Timestamp())))) {
return NS_ERROR_FAILURE;
}
- if (!JS_DefineProperty(cx, rootObj, processEvents[i].first(), eventsArray, JSPROP_ENUMERATE)) {
+ // Add category, method, object.
+ const char* strings[] = {
+ info.common_info.category(),
+ info.method(),
+ info.object(),
+ };
+ for (const char* s : strings) {
+ const NS_ConvertUTF8toUTF16 wide(s);
+ if (!items.append(JS::StringValue(JS_NewUCStringCopyN(cx, wide.Data(), wide.Length())))) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ // Add the optional string value only when needed.
+ // When extra is empty and this has no value, we can save a little space.
+ if (record.Value()) {
+ const NS_ConvertUTF8toUTF16 wide(record.Value().value());
+ if (!items.append(JS::StringValue(JS_NewUCStringCopyN(cx, wide.Data(), wide.Length())))) {
+ return NS_ERROR_FAILURE;
+ }
+ } else if (!record.Extra().IsEmpty()) {
+ if (!items.append(JS::NullValue())) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ // Add the optional extra dictionary.
+ // To save a little space, only add it when it is not empty.
+ if (!record.Extra().IsEmpty()) {
+ JS::RootedObject obj(cx, JS_NewPlainObject(cx));
+ if (!obj) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Add extra key & value entries.
+ const ExtraArray& extra = record.Extra();
+ for (uint32_t i = 0; i < extra.Length(); ++i) {
+ const NS_ConvertUTF8toUTF16 wide(extra[i].value);
+ JS::Rooted<JS::Value> value(cx);
+ value.setString(JS_NewUCStringCopyN(cx, wide.Data(), wide.Length()));
+
+ if (!JS_DefineProperty(cx, obj, extra[i].key.get(), value, JSPROP_ENUMERATE)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ val.setObject(*obj);
+
+ if (!items.append(val)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ // Add the record to the events array.
+ JS::RootedObject itemsArray(cx, JS_NewArrayObject(cx, items));
+ if (!JS_DefineElement(cx, eventsArray, i, itemsArray, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
}
- aResult.setObject(*rootObj);
+ aResult.setObject(*eventsArray);
return NS_OK;
}
/**
* Resets all the stored events. This is intended to be only used in tests.
*/
void
TelemetryEvent::ClearEvents()
{
StaticMutexAutoLock lock(gTelemetryEventsMutex);
if (!gInitDone) {
return;
}
- gEventRecords.Clear();
+ gEventRecords->Clear();
}
void
TelemetryEvent::SetEventRecordingEnabled(const nsACString& category, bool enabled)
{
StaticMutexAutoLock locker(gTelemetryEventsMutex);
uint32_t categoryId;
@@ -788,26 +704,19 @@ TelemetryEvent::SetEventRecordingEnabled
}
size_t
TelemetryEvent::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
StaticMutexAutoLock locker(gTelemetryEventsMutex);
size_t n = 0;
-
- n += gEventRecords.ShallowSizeOfExcludingThis(aMallocSizeOf);
- for (auto iter = gEventRecords.Iter(); !iter.Done(); iter.Next()) {
- EventRecordArray* eventRecords = static_cast<EventRecordArray*>(iter.Data());
- n += eventRecords->ShallowSizeOfIncludingThis(aMallocSizeOf);
-
- const uint32_t len = eventRecords->Length();
- for (uint32_t i = 0; i < len; ++i) {
- n += (*eventRecords)[i].SizeOfExcludingThis(aMallocSizeOf);
- }
+ n += gEventRecords->ShallowSizeOfIncludingThis(aMallocSizeOf);
+ for (uint32_t i = 0; i < gEventRecords->Length(); ++i) {
+ n += (*gEventRecords)[i].SizeOfExcludingThis(aMallocSizeOf);
}
n += gEventNameIDMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (auto iter = gEventNameIDMap.ConstIter(); !iter.Done(); iter.Next()) {
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
n += gCategoryNameIDMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
--- a/toolkit/components/telemetry/TelemetryEvent.h
+++ b/toolkit/components/telemetry/TelemetryEvent.h
@@ -3,22 +3,16 @@
* 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 TelemetryEvent_h__
#define TelemetryEvent_h__
#include "mozilla/TelemetryEventEnums.h"
-namespace mozilla {
-namespace Telemetry {
- struct ChildEventData;
-}
-}
-
// This module is internal to Telemetry. It encapsulates Telemetry's
// event recording and storage logic. It should only be used by
// Telemetry.cpp. These functions should not be used anywhere else.
// For the public interface to Telemetry functionality, see Telemetry.h.
namespace TelemetryEvent {
void InitializeGlobalState(bool canRecordBase, bool canRecordExtended);
@@ -31,20 +25,16 @@ void SetCanRecordExtended(bool b);
nsresult RecordEvent(const nsACString& aCategory, const nsACString& aMethod,
const nsACString& aObject, JS::HandleValue aValue,
JS::HandleValue aExtra, JSContext* aCx,
uint8_t optional_argc);
void SetEventRecordingEnabled(const nsACString& aCategory, bool aEnabled);
nsresult CreateSnapshots(uint32_t aDataset, bool aClear, JSContext* aCx,
uint8_t optional_argc, JS::MutableHandleValue aResult);
-// Record events from child processes.
-nsresult RecordChildEvents(GeckoProcessType aProcessType,
- const nsTArray<mozilla::Telemetry::ChildEventData>& aEvents);
-
// Only to be used for testing.
void ClearEvents();
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
} // namespace TelemetryEvent
#endif // TelemetryEvent_h__
--- a/toolkit/components/telemetry/TelemetrySession.jsm
+++ b/toolkit/components/telemetry/TelemetrySession.jsm
@@ -1023,27 +1023,25 @@ var Impl = {
getEvents(isSubsession, clearSubsession) {
if (!isSubsession) {
// We only support scalars for subsessions.
this._log.trace("getEvents - We only support events in subsessions.");
return [];
}
- let snapshot = Telemetry.snapshotBuiltinEvents(this.getDatasetType(),
- clearSubsession);
+ let events = Telemetry.snapshotBuiltinEvents(this.getDatasetType(),
+ clearSubsession);
// Don't return the test events outside of test environments.
if (!this._testing) {
- for (let proc of Object.keys(snapshot)) {
- snapshot[proc] = snapshot[proc].filter(e => !e[1].startsWith("telemetry.test"));
- }
+ events = events.filter(e => !e[1].startsWith("telemetry.test"));
}
- return snapshot;
+ return events;
},
getThreadHangStats: function getThreadHangStats(stats) {
stats.forEach((thread) => {
thread.activity = this.packHistogram(thread.activity);
thread.hangs.forEach((hang) => {
hang.histogram = this.packHistogram(hang.histogram);
});
@@ -1293,46 +1291,43 @@ var Impl = {
return payloadObj;
}
// Additional payload for chrome process.
let histograms = protect(() => this.getHistograms(isSubsession, clearSubsession), {});
let keyedHistograms = protect(() => this.getKeyedHistograms(isSubsession, clearSubsession), {});
let scalars = protect(() => this.getScalars(isSubsession, clearSubsession), {});
let keyedScalars = protect(() => this.getScalars(isSubsession, clearSubsession, true), {});
- let events = protect(() => this.getEvents(isSubsession, clearSubsession))
payloadObj.histograms = histograms[HISTOGRAM_SUFFIXES.PARENT] || {};
payloadObj.keyedHistograms = keyedHistograms[HISTOGRAM_SUFFIXES.PARENT] || {};
payloadObj.processes = {
parent: {
scalars: scalars[INTERNAL_PROCESSES_NAMES.PARENT] || {},
keyedScalars: keyedScalars[INTERNAL_PROCESSES_NAMES.PARENT] || {},
- events: events[INTERNAL_PROCESSES_NAMES.PARENT] || [],
+ events: protect(() => this.getEvents(isSubsession, clearSubsession)),
},
content: {
scalars: scalars[INTERNAL_PROCESSES_NAMES.CONTENT],
keyedScalars: keyedScalars[INTERNAL_PROCESSES_NAMES.CONTENT],
histograms: histograms[HISTOGRAM_SUFFIXES.CONTENT],
keyedHistograms: keyedHistograms[HISTOGRAM_SUFFIXES.CONTENT],
- events: events[INTERNAL_PROCESSES_NAMES.CONTENT] || [],
},
};
// Only include the GPU process if we've accumulated data for it.
if (HISTOGRAM_SUFFIXES.GPU in histograms ||
HISTOGRAM_SUFFIXES.GPU in keyedHistograms ||
INTERNAL_PROCESSES_NAMES.GPU in scalars ||
INTERNAL_PROCESSES_NAMES.GPU in keyedScalars) {
payloadObj.processes.gpu = {
scalars: scalars[INTERNAL_PROCESSES_NAMES.GPU],
keyedScalars: keyedScalars[INTERNAL_PROCESSES_NAMES.GPU],
histograms: histograms[HISTOGRAM_SUFFIXES.GPU],
keyedHistograms: keyedHistograms[HISTOGRAM_SUFFIXES.GPU],
- events: events[INTERNAL_PROCESSES_NAMES.GPU] || [],
};
}
payloadObj.info = info;
// Add extended set measurements for chrome process.
if (Telemetry.canRecordExtended) {
payloadObj.slowSQL = protect(() => Telemetry.slowSQL);
--- a/toolkit/components/telemetry/ipc/TelemetryComms.h
+++ b/toolkit/components/telemetry/ipc/TelemetryComms.h
@@ -54,30 +54,16 @@ struct KeyedScalarAction
ScalarID mId;
ScalarActionType mActionType;
nsCString mKey;
// We need to wrap mData in a Maybe otherwise the IPC system
// is unable to instantiate a ScalarAction.
Maybe<ScalarVariant> mData;
};
-struct EventExtraEntry {
- nsCString key;
- nsCString value;
-};
-
-struct ChildEventData {
- double timestamp;
- nsCString category;
- nsCString method;
- nsCString object;
- mozilla::Maybe<nsCString> value;
- nsTArray<EventExtraEntry> extra;
-};
-
} // namespace Telemetry
} // namespace mozilla
namespace IPC {
template<>
struct
ParamTraits<mozilla::Telemetry::Accumulation>
@@ -297,65 +283,11 @@ ParamTraits<mozilla::Telemetry::KeyedSca
MOZ_ASSERT(false, "Unknown keyed scalar type.");
return false;
}
return true;
}
};
-template<>
-struct
-ParamTraits<mozilla::Telemetry::ChildEventData>
-{
- typedef mozilla::Telemetry::ChildEventData paramType;
-
- static void Write(Message* aMsg, const paramType& aParam)
- {
- WriteParam(aMsg, aParam.timestamp);
- WriteParam(aMsg, aParam.category);
- WriteParam(aMsg, aParam.method);
- WriteParam(aMsg, aParam.object);
- WriteParam(aMsg, aParam.value);
- WriteParam(aMsg, aParam.extra);
- }
-
- static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
- {
- if (!ReadParam(aMsg, aIter, &(aResult->timestamp)) ||
- !ReadParam(aMsg, aIter, &(aResult->category)) ||
- !ReadParam(aMsg, aIter, &(aResult->method)) ||
- !ReadParam(aMsg, aIter, &(aResult->object)) ||
- !ReadParam(aMsg, aIter, &(aResult->value)) ||
- !ReadParam(aMsg, aIter, &(aResult->extra))) {
- return false;
- }
-
- return true;
- }
-};
-
-template<>
-struct
-ParamTraits<mozilla::Telemetry::EventExtraEntry>
-{
- typedef mozilla::Telemetry::EventExtraEntry paramType;
-
- static void Write(Message* aMsg, const paramType& aParam)
- {
- WriteParam(aMsg, aParam.key);
- WriteParam(aMsg, aParam.value);
- }
-
- static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
- {
- if (!ReadParam(aMsg, aIter, &(aResult->key)) ||
- !ReadParam(aMsg, aIter, &(aResult->value))) {
- return false;
- }
-
- return true;
- }
-};
-
} // namespace IPC
#endif // Telemetry_Comms_h__
--- a/toolkit/components/telemetry/ipc/TelemetryIPC.cpp
+++ b/toolkit/components/telemetry/ipc/TelemetryIPC.cpp
@@ -2,17 +2,16 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "TelemetryIPC.h"
#include "../TelemetryScalar.h"
#include "../TelemetryHistogram.h"
-#include "../TelemetryEvent.h"
namespace mozilla {
void
TelemetryIPC::AccumulateChildHistograms(GeckoProcessType aProcessType,
const nsTArray<Telemetry::Accumulation>& aAccumulations)
{
TelemetryHistogram::AccumulateChild(aProcessType, aAccumulations);
@@ -34,15 +33,9 @@ TelemetryIPC::UpdateChildScalars(GeckoPr
void
TelemetryIPC::UpdateChildKeyedScalars(GeckoProcessType aProcessType,
const nsTArray<Telemetry::KeyedScalarAction>& aScalarActions)
{
TelemetryScalar::UpdateChildKeyedData(aProcessType, aScalarActions);
}
-void
-TelemetryIPC::RecordChildEvents(GeckoProcessType aProcessType, const nsTArray<Telemetry::ChildEventData>& aEvents)
-{
- TelemetryEvent::RecordChildEvents(aProcessType, aEvents);
}
-
-}
--- a/toolkit/components/telemetry/ipc/TelemetryIPC.h
+++ b/toolkit/components/telemetry/ipc/TelemetryIPC.h
@@ -15,58 +15,45 @@
namespace mozilla {
namespace Telemetry {
struct Accumulation;
struct KeyedAccumulation;
struct ScalarAction;
struct KeyedScalarAction;
-struct ChildEventData;
}
namespace TelemetryIPC {
/**
* Accumulate child process data into histograms for the given process type.
*
- * @param aProcessType - the process type to accumulate the histograms for
* @param aAccumulations - accumulation actions to perform
*/
void AccumulateChildHistograms(GeckoProcessType aProcessType, const nsTArray<Telemetry::Accumulation>& aAccumulations);
/**
* Accumulate child process data into keyed histograms for the given process type.
*
- * @param aProcessType - the process type to accumulate the keyed histograms for
* @param aAccumulations - accumulation actions to perform
*/
void AccumulateChildKeyedHistograms(GeckoProcessType aProcessType, const nsTArray<Telemetry::KeyedAccumulation>& aAccumulations);
/**
* Update scalars for the given process type with the data coming from child process.
*
- * @param aProcessType - the process type to process the scalar actions for
* @param aScalarActions - actions to update the scalar data
*/
void UpdateChildScalars(GeckoProcessType aProcessType, const nsTArray<Telemetry::ScalarAction>& aScalarActions);
/**
- * Update keyed scalars for the given process type with the data coming from child process.
+ * Update keyed scalars for the given process type with the data coming from child process.
*
- * @param aProcessType - the process type to process the keyed scalar actions for
* @param aScalarActions - actions to update the keyed scalar data
*/
void UpdateChildKeyedScalars(GeckoProcessType aProcessType, const nsTArray<Telemetry::KeyedScalarAction>& aScalarActions);
-/**
- * Record events for the given process type with the data coming from child process.
- *
- * @param aProcessType - the process type to record the events for
- * @param aEvents - events to record
- */
-void RecordChildEvents(GeckoProcessType aProcessType, const nsTArray<Telemetry::ChildEventData>& aEvents);
-
}
}
#endif // TelemetryIPC_h__
--- a/toolkit/components/telemetry/ipc/TelemetryIPCAccumulator.cpp
+++ b/toolkit/components/telemetry/ipc/TelemetryIPCAccumulator.cpp
@@ -22,55 +22,52 @@ using mozilla::StaticMutex;
using mozilla::StaticMutexAutoLock;
using mozilla::StaticAutoPtr;
using mozilla::Telemetry::Accumulation;
using mozilla::Telemetry::KeyedAccumulation;
using mozilla::Telemetry::ScalarActionType;
using mozilla::Telemetry::ScalarAction;
using mozilla::Telemetry::KeyedScalarAction;
using mozilla::Telemetry::ScalarVariant;
-using mozilla::Telemetry::ChildEventData;
namespace TelemetryIPCAccumulator = mozilla::TelemetryIPCAccumulator;
// Sending each remote accumulation immediately places undue strain on the
// IPC subsystem. Batch the remote accumulations for a period of time before
// sending them all at once. This value was chosen as a balance between data
// timeliness and performance (see bug 1218576)
const uint32_t kBatchTimeoutMs = 2000;
// To stop growing unbounded in memory while waiting for kBatchTimeoutMs to
// drain the g*Accumulations arrays, request an immediate flush if the arrays
// manage to reach this high water mark of elements.
const size_t kHistogramAccumulationsArrayHighWaterMark = 5 * 1024;
-// This timer is used for batching and sending child process accumulations to the parent.
+// For batching and sending child process accumulations to the parent
nsITimer* gIPCTimer = nullptr;
mozilla::Atomic<bool, mozilla::Relaxed> gIPCTimerArmed(false);
mozilla::Atomic<bool, mozilla::Relaxed> gIPCTimerArming(false);
-// This batches child process accumulations that should be sent to the parent.
+// For batching and sending child process accumulations to the parent
StaticAutoPtr<nsTArray<Accumulation>> gHistogramAccumulations;
StaticAutoPtr<nsTArray<KeyedAccumulation>> gKeyedHistogramAccumulations;
StaticAutoPtr<nsTArray<ScalarAction>> gChildScalarsActions;
StaticAutoPtr<nsTArray<KeyedScalarAction>> gChildKeyedScalarsActions;
-StaticAutoPtr<nsTArray<ChildEventData>> gChildEvents;
// This is a StaticMutex rather than a plain Mutex so that (1)
// it gets initialised in a thread-safe manner the first time
// it is used, and (2) because it is never de-initialised, and
// a normal Mutex would show up as a leak in BloatView. StaticMutex
// also has the "OffTheBooks" property, so it won't show as a leak
// in BloatView.
static StaticMutex gTelemetryIPCAccumulatorMutex;
namespace {
-void
-DoArmIPCTimerMainThread(const StaticMutexAutoLock& lock)
+void DoArmIPCTimerMainThread(const StaticMutexAutoLock& lock)
{
MOZ_ASSERT(NS_IsMainThread());
gIPCTimerArming = false;
if (gIPCTimerArmed) {
return;
}
if (!gIPCTimer) {
CallCreateInstance(NS_TIMER_CONTRACTID, &gIPCTimer);
@@ -79,18 +76,17 @@ DoArmIPCTimerMainThread(const StaticMute
gIPCTimer->InitWithNamedFuncCallback(TelemetryIPCAccumulator::IPCTimerFired,
nullptr, kBatchTimeoutMs,
nsITimer::TYPE_ONE_SHOT,
"TelemetryIPCAccumulator::IPCTimerFired");
gIPCTimerArmed = true;
}
}
-void
-ArmIPCTimer(const StaticMutexAutoLock& lock)
+void ArmIPCTimer(const StaticMutexAutoLock& lock)
{
if (gIPCTimerArmed || gIPCTimerArming) {
return;
}
gIPCTimerArming = true;
if (NS_IsMainThread()) {
DoArmIPCTimerMainThread(lock);
} else {
@@ -170,68 +166,43 @@ TelemetryIPCAccumulator::RecordChildKeye
gChildKeyedScalarsActions = new nsTArray<KeyedScalarAction>();
}
// Store the action.
gChildKeyedScalarsActions->AppendElement(
KeyedScalarAction{aId, aAction, NS_ConvertUTF16toUTF8(aKey), Some(aValue)});
ArmIPCTimer(locker);
}
-void
-TelemetryIPCAccumulator::RecordChildEvent(double timestamp,
- const nsACString& category,
- const nsACString& method,
- const nsACString& object,
- const mozilla::Maybe<nsCString>& value,
- const nsTArray<mozilla::Telemetry::EventExtraEntry>& extra)
-{
- StaticMutexAutoLock locker(gTelemetryIPCAccumulatorMutex);
- if (!gChildEvents) {
- gChildEvents = new nsTArray<ChildEventData>();
- }
- // Store the action.
- gChildEvents->AppendElement(ChildEventData{timestamp, nsCString(category),
- nsCString(method), nsCString(object),
- value,
- nsTArray<mozilla::Telemetry::EventExtraEntry>(extra)});
- ArmIPCTimer(locker);
-}
-
// This method takes the lock only to double-buffer the batched telemetry.
// It releases the lock before calling out to IPC code which can (and does)
// Accumulate (which would deadlock)
template<class TActor>
static void
SendAccumulatedData(TActor* ipcActor)
{
// Get the accumulated data and free the storage buffers.
nsTArray<Accumulation> accumulationsToSend;
nsTArray<KeyedAccumulation> keyedAccumulationsToSend;
nsTArray<ScalarAction> scalarsToSend;
nsTArray<KeyedScalarAction> keyedScalarsToSend;
- nsTArray<ChildEventData> eventsToSend;
-
{
StaticMutexAutoLock locker(gTelemetryIPCAccumulatorMutex);
if (gHistogramAccumulations) {
accumulationsToSend.SwapElements(*gHistogramAccumulations);
}
if (gKeyedHistogramAccumulations) {
keyedAccumulationsToSend.SwapElements(*gKeyedHistogramAccumulations);
}
// Copy the scalar actions.
if (gChildScalarsActions) {
scalarsToSend.SwapElements(*gChildScalarsActions);
}
if (gChildKeyedScalarsActions) {
keyedScalarsToSend.SwapElements(*gChildKeyedScalarsActions);
}
- if (gChildEvents) {
- eventsToSend.SwapElements(*gChildEvents);
- }
}
// Send the accumulated data to the parent process.
mozilla::Unused << NS_WARN_IF(!ipcActor);
if (accumulationsToSend.Length()) {
mozilla::Unused <<
NS_WARN_IF(!ipcActor->SendAccumulateChildHistograms(accumulationsToSend));
}
@@ -242,20 +213,16 @@ SendAccumulatedData(TActor* ipcActor)
if (scalarsToSend.Length()) {
mozilla::Unused <<
NS_WARN_IF(!ipcActor->SendUpdateChildScalars(scalarsToSend));
}
if (keyedScalarsToSend.Length()) {
mozilla::Unused <<
NS_WARN_IF(!ipcActor->SendUpdateChildKeyedScalars(keyedScalarsToSend));
}
- if (eventsToSend.Length()) {
- mozilla::Unused <<
- NS_WARN_IF(!ipcActor->SendRecordChildEvents(eventsToSend));
- }
}
// To ensure we don't loop IPCTimerFired->AccumulateChild->arm timer, we don't
// unset gIPCTimerArmed until the IPC completes
//
// This function must be called on the main thread, otherwise IPC will fail.
void
@@ -288,17 +255,16 @@ TelemetryIPCAccumulator::DeInitializeGlo
if (gIPCTimer) {
NS_RELEASE(gIPCTimer);
}
gHistogramAccumulations = nullptr;
gKeyedHistogramAccumulations = nullptr;
gChildScalarsActions = nullptr;
gChildKeyedScalarsActions = nullptr;
- gChildEvents = nullptr;
}
void
TelemetryIPCAccumulator::DispatchToMainThread(already_AddRefed<nsIRunnable>&& aEvent)
{
nsCOMPtr<nsIRunnable> event(aEvent);
nsCOMPtr<nsIThread> thread;
nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
--- a/toolkit/components/telemetry/ipc/TelemetryIPCAccumulator.h
+++ b/toolkit/components/telemetry/ipc/TelemetryIPCAccumulator.h
@@ -2,17 +2,16 @@
/* 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 TelemetryIPCAccumulator_h__
#define TelemetryIPCAccumulator_h__
#include "mozilla/AlreadyAddRefed.h"
-#include "mozilla/Maybe.h"
#include "TelemetryComms.h"
class nsIRunnable;
class nsITimer;
class nsAString;
class nsCString;
namespace mozilla {
@@ -27,23 +26,16 @@ void AccumulateChildKeyedHistogram(mozil
void RecordChildScalarAction(mozilla::Telemetry::ScalarID aId,
mozilla::Telemetry::ScalarActionType aAction,
const mozilla::Telemetry::ScalarVariant& aValue);
void RecordChildKeyedScalarAction(mozilla::Telemetry::ScalarID aId, const nsAString& aKey,
mozilla::Telemetry::ScalarActionType aAction,
const mozilla::Telemetry::ScalarVariant& aValue);
-void RecordChildEvent(double timestamp,
- const nsACString& category,
- const nsACString& method,
- const nsACString& object,
- const mozilla::Maybe<nsCString>& value,
- const nsTArray<mozilla::Telemetry::EventExtraEntry>& extra);
-
void IPCTimerFired(nsITimer* aTimer, void* aClosure);
void DeInitializeGlobalState();
void DispatchToMainThread(already_AddRefed<nsIRunnable>&& aEvent);
}
}
deleted file mode 100644
--- a/toolkit/components/telemetry/tests/unit/test_ChildEvents.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/
-*/
-
-Cu.import("resource://gre/modules/Services.jsm", this);
-Cu.import("resource://gre/modules/TelemetryController.jsm", this);
-Cu.import("resource://gre/modules/TelemetrySession.jsm", this);
-Cu.import("resource://gre/modules/PromiseUtils.jsm", this);
-Cu.import("resource://testing-common/ContentTaskUtils.jsm", this);
-
-const MESSAGE_CHILD_TEST_DONE = "ChildTest:Done";
-
-const PLATFORM_VERSION = "1.9.2";
-const APP_VERSION = "1";
-const APP_ID = "xpcshell@tests.mozilla.org";
-const APP_NAME = "XPCShell";
-
-const RECORDED_CONTENT_EVENTS = [
- ["telemetry.test", "test1", "object1"],
- ["telemetry.test", "test1", "object1", null, {"key1": "x", "key2": "y"}],
- ["telemetry.test", "test1", "object1", "foo", {"key1": "x", "key2": "y"}],
-];
-
-function run_child_test() {
- // Record some events in the "content" process.
- RECORDED_CONTENT_EVENTS.forEach(e => Telemetry.recordEvent(...e));
-}
-
-/**
- * This function waits until content events are reported into the
- * events snapshot.
- */
-function* waitForContentEvents() {
- yield ContentTaskUtils.waitForCondition(() => {
- const snapshot =
- Telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
- return Object.keys(snapshot).includes("tab");
- });
-}
-
-add_task(function*() {
- if (!runningInParent) {
- TelemetryController.testSetupContent();
- run_child_test();
- do_send_remote_message(MESSAGE_CHILD_TEST_DONE);
- return;
- }
-
- // Setup.
- do_get_profile(true);
- loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION);
- Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, true);
- yield TelemetryController.testSetup();
- // Make sure we don't generate unexpected pings due to pref changes.
- yield setEmptyPrefWatchlist();
- // Enable recording for the test event category.
- Telemetry.setEventRecordingEnabled("telemetry.test", true);
-
- // Run test in child, don't wait for it to finish: just wait for the
- // MESSAGE_CHILD_TEST_DONE.
- run_test_in_child("test_ChildEvents.js");
- yield do_await_remote_message(MESSAGE_CHILD_TEST_DONE);
-
- // Once events are set by the content process, they don't immediately get
- // sent to the parent process. Wait for the Telemetry IPC Timer to trigger
- // and batch send the data back to the parent process.
- yield waitForContentEvents();
-
- // Get an "environment-changed" ping rather than a "test-ping", as
- // event measurements are only supported in subsession pings.
- const payload = TelemetrySession.getPayload("environment-change");
-
- // Validate the event data.
- Assert.ok("processes" in payload, "Should have processes section");
- Assert.ok("parent" in payload.processes, "Should have main process section");
- Assert.ok("events" in payload.processes.parent, "Main process section should have events.");
- Assert.ok("content" in payload.processes, "Should have child process section");
- Assert.ok("events" in payload.processes.content, "Child process section should have events.");
-
- let events = payload.processes.content.events.map(e => e.slice(1));
- Assert.deepEqual(events, RECORDED_CONTENT_EVENTS, "Should have recorded content events.");
-
- // Make sure all events are cleared from storage properly.
- let snapshot =
- Telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 1, "Should have events from one process.");
- snapshot =
- Telemetry.snapshotBuiltinEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 0, "Should have cleared all events from storage.");
-});
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryEvents.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEvents.js
@@ -40,42 +40,39 @@ add_task(function* test_recording_state(
const events = [
["telemetry.test", "test1", "object1"],
["telemetry.test.second", "test", "object1"],
];
// Both test categories should be off by default.
events.forEach(e => Telemetry.recordEvent(...e));
let snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 0, "Should not have recorded any events.");
+ Assert.deepEqual(snapshot, [], "Should not have recorded any events.");
// Enable one test category and see that we record correctly.
Telemetry.setEventRecordingEnabled("telemetry.test", true);
events.forEach(e => Telemetry.recordEvent(...e));
snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- Assert.equal(snapshot.default.length, 1, "Should have recorded one event.");
- Assert.equal(snapshot.default[0][1], "telemetry.test", "Should have recorded one event in telemetry.test");
+ Assert.equal(snapshot.length, 1, "Should have recorded one event.");
+ Assert.equal(snapshot[0][1], "telemetry.test", "Should have recorded one event in telemetry.test");
// Also enable the other test category and see that we record correctly.
Telemetry.setEventRecordingEnabled("telemetry.test.second", true);
events.forEach(e => Telemetry.recordEvent(...e));
snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- Assert.equal(snapshot.default.length, 2, "Should have recorded two events.");
- Assert.equal(snapshot.default[0][1], "telemetry.test", "Should have recorded one event in telemetry.test");
- Assert.equal(snapshot.default[1][1], "telemetry.test.second", "Should have recorded one event in telemetry.test.second");
+ Assert.equal(snapshot.length, 2, "Should have recorded two events.");
+ Assert.equal(snapshot[0][1], "telemetry.test", "Should have recorded one event in telemetry.test");
+ Assert.equal(snapshot[1][1], "telemetry.test.second", "Should have recorded one event in telemetry.test.second");
// Now turn of one category again and check that this works as expected.
Telemetry.setEventRecordingEnabled("telemetry.test", false);
events.forEach(e => Telemetry.recordEvent(...e));
snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- Assert.equal(snapshot.default.length, 1, "Should have recorded one event.");
- Assert.equal(snapshot.default[0][1], "telemetry.test.second", "Should have recorded one event in telemetry.test.second");
+ Assert.equal(snapshot.length, 1, "Should have recorded one event.");
+ Assert.equal(snapshot[0][1], "telemetry.test.second", "Should have recorded one event in telemetry.test.second");
});
add_task(function* recording_setup() {
// Make sure both test categories are enabled for the remaining tests.
// Otherwise their event recording won't work.
Telemetry.setEventRecordingEnabled("telemetry.test", true);
Telemetry.setEventRecordingEnabled("telemetry.test.second", true);
});
@@ -140,105 +137,99 @@ add_task(function* test_recording() {
let recordedData = events[i].slice(1);
let expectedData = expectedEvents[i].event.slice();
Assert.deepEqual(recordedData, expectedData, "The recorded event data should match.");
}
};
// Check that the expected events were recorded.
- let snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, false);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- checkEvents(snapshot.default, expected);
+ let events = Telemetry.snapshotBuiltinEvents(OPTIN, false);
+ checkEvents(events, expected);
// Check serializing only opt-out events.
- snapshot = Telemetry.snapshotBuiltinEvents(OPTOUT, false);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
+ events = Telemetry.snapshotBuiltinEvents(OPTOUT, false);
let filtered = expected.filter(e => e.optout == true);
- checkEvents(snapshot.default, filtered);
+ checkEvents(events, filtered);
});
add_task(function* test_clear() {
Telemetry.clearEvents();
const COUNT = 10;
for (let i = 0; i < COUNT; ++i) {
Telemetry.recordEvent("telemetry.test", "test1", "object1");
Telemetry.recordEvent("telemetry.test.second", "test", "object1");
}
// Check that events were recorded.
// The events are cleared by passing the respective flag.
- let snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- Assert.equal(snapshot.default.length, 2 * COUNT, `Should have recorded ${2 * COUNT} events.`);
+ let events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
+ Assert.equal(events.length, 2 * COUNT, `Should have recorded ${2 * COUNT} events.`);
// Now the events should be cleared.
- snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, false);
- Assert.equal(Object.keys(snapshot).length, 0, `Should have cleared the events.`);
+ events = Telemetry.snapshotBuiltinEvents(OPTIN, false);
+ Assert.equal(events.length, 0, `Should have cleared the events.`);
});
add_task(function* test_expiry() {
Telemetry.clearEvents();
// Recording call with event that is expired by version.
Telemetry.recordEvent("telemetry.test", "expired_version", "object1");
- let snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 0, "Should not record event with expired version.");
+ let events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
+ Assert.equal(events.length, 0, "Should not record event with expired version.");
// Recording call with event that is expired by date.
Telemetry.recordEvent("telemetry.test", "expired_date", "object1");
- snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 0, "Should not record event with expired date.");
+ events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
+ Assert.equal(events.length, 0, "Should not record event with expired date.");
// Recording call with event that has expiry_version and expiry_date in the future.
Telemetry.recordEvent("telemetry.test", "not_expired_optout", "object1");
- snapshot = Telemetry.snapshotBuiltinEvents(OPTOUT, true);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- Assert.equal(snapshot.default.length, 1, "Should record event when date and version are not expired.");
+ events = Telemetry.snapshotBuiltinEvents(OPTOUT, true);
+ Assert.equal(events.length, 1, "Should record event when date and version are not expired.");
});
add_task(function* test_invalidParams() {
Telemetry.clearEvents();
// Recording call with wrong type for value argument.
Telemetry.recordEvent("telemetry.test", "test1", "object1", 1);
- let snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 0, "Should not record event when value argument with invalid type is passed.");
+ let events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
+ Assert.equal(events.length, 0, "Should not record event when value argument with invalid type is passed.");
// Recording call with wrong type for extra argument.
Telemetry.recordEvent("telemetry.test", "test1", "object1", null, "invalid");
- snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 0, "Should not record event when extra argument with invalid type is passed.");
+ events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
+ Assert.equal(events.length, 0, "Should not record event when extra argument with invalid type is passed.");
// Recording call with unknown extra key.
Telemetry.recordEvent("telemetry.test", "test1", "object1", null, {"key3": "x"});
- snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 0, "Should not record event when extra argument with invalid key is passed.");
+ events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
+ Assert.equal(events.length, 0, "Should not record event when extra argument with invalid key is passed.");
// Recording call with invalid value type.
Telemetry.recordEvent("telemetry.test", "test1", "object1", null, {"key3": 1});
- snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.equal(Object.keys(snapshot).length, 0, "Should not record event when extra argument with invalid value type is passed.");
+ events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
+ Assert.equal(events.length, 0, "Should not record event when extra argument with invalid value type is passed.");
});
add_task(function* test_storageLimit() {
Telemetry.clearEvents();
// Record more events than the storage limit allows.
let LIMIT = 1000;
let COUNT = LIMIT + 10;
for (let i = 0; i < COUNT; ++i) {
Telemetry.recordEvent("telemetry.test", "test1", "object1", String(i));
}
// Check that the right events were recorded.
- let snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- let events = snapshot.default;
+ let events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
Assert.equal(events.length, LIMIT, `Should have only recorded ${LIMIT} events`);
Assert.ok(events.every((e, idx) => e[4] === String(idx)),
"Should have recorded all events from before hitting the limit.");
});
add_task(function* test_valueLimits() {
Telemetry.clearEvents();
@@ -269,19 +260,17 @@ add_task(function* test_valueLimits() {
// Strip off trailing null values to match the serialized events.
for (let e of expected) {
while ((e.length >= 3) && (e[e.length - 1] === null)) {
e.pop();
}
}
// Check that the right events were recorded.
- let snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- let events = snapshot.default;
+ let events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
Assert.equal(events.length, expected.length,
"Should have recorded the expected number of events");
for (let i = 0; i < expected.length; ++i) {
Assert.deepEqual(events[i].slice(1), expected[i],
"Should have recorded the expected event data.");
}
});
@@ -289,15 +278,13 @@ add_task(function* test_unicodeValues()
Telemetry.clearEvents();
// Record string values containing unicode characters.
let value = "漢語";
Telemetry.recordEvent("telemetry.test", "test1", "object1", value);
Telemetry.recordEvent("telemetry.test", "test1", "object1", null, {"key1": value});
// Check that the values were correctly recorded.
- let snapshot = Telemetry.snapshotBuiltinEvents(OPTIN, true);
- Assert.ok(("default" in snapshot), "Should have entry for main process.");
- let events = snapshot.default;
+ let events = Telemetry.snapshotBuiltinEvents(OPTIN, true);
Assert.equal(events.length, 2, "Should have recorded 2 events.");
Assert.equal(events[0][4], value, "Should have recorded the right value.");
Assert.equal(events[1][5]["key1"], value, "Should have recorded the right extra value.");
});
--- a/toolkit/components/telemetry/tests/unit/xpcshell.ini
+++ b/toolkit/components/telemetry/tests/unit/xpcshell.ini
@@ -51,24 +51,22 @@ tags = addons
skip-if = os == "android" # Disabled due to intermittent orange on Android
tags = addons
[test_TelemetrySession.js]
tags = addons
[test_ThreadHangStats.js]
run-sequentially = Bug 1046307, test can fail intermittently when CPU load is high
[test_TelemetrySend.js]
[test_ChildHistograms.js]
-skip-if = os == "android" # Disabled due to crashes (see bug 1331366)
+skip-if = os == "android"
tags = addons
[test_ChildScalars.js]
skip-if = os == "android" # Disabled due to crashes (see bug 1331366)
[test_TelemetryReportingPolicy.js]
tags = addons
[test_TelemetryScalars.js]
[test_TelemetryTimestamps.js]
skip-if = toolkit == 'android'
[test_TelemetryCaptureStack.js]
[test_TelemetryEvents.js]
-[test_ChildEvents.js]
-skip-if = os == "android" # Disabled due to crashes (see bug 1331366)
[test_TelemetryModules.js]
[test_PingSender.js]
skip-if = (os == "android") || (os == "linux" && bits == 32)