bug 1369041 - Allow child processes to discard data when overwhelmed r?gfritzsche f?bsmedberg
It is possible in extreme cases that the Telemetry IPC Accumulator might be
starved long enough that it cannot drain its stored accumulations for a while.
Once we hit 5x the high water mark, start discarding data.
Count each piece and type of discarded data and report it via a custom IPC
message.
MozReview-Commit-ID: JayRpa5QPec
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5189,16 +5189,25 @@ ContentParent::RecvUpdateChildKeyedScala
mozilla::ipc::IPCResult
ContentParent::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents)
{
TelemetryIPC::RecordChildEvents(GetTelemetryProcessID(mRemoteType), aEvents);
return IPC_OK();
}
+mozilla::ipc::IPCResult
+ContentParent::RecvRecordDiscardedData(
+ const mozilla::Telemetry::DiscardedData& aDiscardedData)
+{
+ TelemetryIPC::RecordDiscardedData(GetTelemetryProcessID(mRemoteType),
+ aDiscardedData);
+ return IPC_OK();
+}
+
//////////////////////////////////////////////////////////////////
// PURLClassifierParent
PURLClassifierParent*
ContentParent::AllocPURLClassifierParent(const Principal& aPrincipal,
const bool& aUseTrackingProtection,
bool* aSuccess)
{
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1169,16 +1169,18 @@ private:
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;
+ virtual mozilla::ipc::IPCResult RecvRecordDiscardedData(
+ const DiscardedData& aDiscardedData) 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
@@ -90,16 +90,17 @@ using mozilla::OriginAttributes from "mo
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.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";
+using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
union ChromeRegistryItem
{
ChromePackage;
OverrideMapping;
SubstitutionMapping;
};
@@ -1083,16 +1084,17 @@ 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);
+ async RecordDiscardedData(DiscardedData data);
sync GetA11yContentId() returns (uint32_t aContentId);
async A11yHandlerControl(uint32_t aPid,
IHandlerControlHolder aHandlerControl);
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -194,16 +194,23 @@ GPUChild::RecvUpdateChildKeyedScalars(In
mozilla::ipc::IPCResult
GPUChild::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents)
{
TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Gpu, aEvents);
return IPC_OK();
}
mozilla::ipc::IPCResult
+GPUChild::RecvRecordDiscardedData(const mozilla::Telemetry::DiscardedData& aDiscardedData)
+{
+ TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Gpu, aDiscardedData);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
GPUChild::RecvNotifyDeviceReset(const GPUDeviceData& aData)
{
gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
mHost->mListener->OnProcessDeviceReset(mHost);
return IPC_OK();
}
bool
--- a/gfx/ipc/GPUChild.h
+++ b/gfx/ipc/GPUChild.h
@@ -45,16 +45,17 @@ public:
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;
+ mozilla::ipc::IPCResult RecvRecordDiscardedData(const DiscardedData& aDiscardedData) 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(const GPUDeviceData& aData) override;
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -15,16 +15,17 @@ include protocol PVideoDecoderManager;
using base::ProcessId from "base/process.h";
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.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";
+using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
namespace mozilla {
namespace gfx {
union GfxPrefValue {
bool;
int32_t;
uint32_t;
@@ -103,16 +104,17 @@ child:
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 RecordDiscardedData(DiscardedData data);
async NotifyDeviceReset(GPUDeviceData status);
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);
};
} // namespace gfx
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -499,16 +499,78 @@ telemetry:
expires: "58"
kind: boolean
notification_emails:
- telemetry-client-dev@mozilla.com
release_channel_collection: opt-out
record_in_processes:
- 'main'
+telemetry.discarded:
+ accumulations:
+ bug_numbers:
+ - 1369041
+ description: >
+ Number of discarded accumulations to histograms in child processes
+ expires: "never"
+ kind: uint
+ notification_emails:
+ - telemetry-client-dev@mozilla.com
+ release_channel_collection: opt-out
+ record_in_processes:
+ - 'all_childs'
+ keyed_accumulations:
+ bug_numbers:
+ - 1369041
+ description: >
+ Number of discarded accumulations to keyed histograms in child processes
+ expires: "never"
+ kind: uint
+ notification_emails:
+ - telemetry-client-dev@mozilla.com
+ release_channel_collection: opt-out
+ record_in_processes:
+ - 'all_childs'
+ scalar_actions:
+ bug_numbers:
+ - 1369041
+ description: >
+ Number of discarded actions on scalars in child processes
+ expires: "never"
+ kind: uint
+ notification_emails:
+ - telemetry-client-dev@mozilla.com
+ release_channel_collection: opt-out
+ record_in_processes:
+ - 'all_childs'
+ keyed_scalar_actions:
+ bug_numbers:
+ - 1369041
+ description: >
+ Number of discarded actions on keyed scalars in child processes
+ expires: "never"
+ kind: uint
+ notification_emails:
+ - telemetry-client-dev@mozilla.com
+ release_channel_collection: opt-out
+ record_in_processes:
+ - 'all_childs'
+ child_events:
+ bug_numbers:
+ - 1369041
+ description: >
+ Number of discarded events in child processes
+ expires: "never"
+ kind: uint
+ notification_emails:
+ - telemetry-client-dev@mozilla.com
+ release_channel_collection: opt-out
+ record_in_processes:
+ - 'all_childs'
+
# The following section is for probes testing the Telemetry system. They will not be
# submitted in pings and are only used for testing.
telemetry.test:
unsigned_int_kind:
bug_numbers:
- 1276190
description: >
This is a test uint type with a really long description, maybe spanning even multiple
--- a/toolkit/components/telemetry/TelemetryScalar.cpp
+++ b/toolkit/components/telemetry/TelemetryScalar.cpp
@@ -27,16 +27,17 @@ using mozilla::StaticMutex;
using mozilla::StaticMutexAutoLock;
using mozilla::Telemetry::Common::AutoHashtable;
using mozilla::Telemetry::Common::IsExpiredVersion;
using mozilla::Telemetry::Common::CanRecordDataset;
using mozilla::Telemetry::Common::IsInDataset;
using mozilla::Telemetry::Common::LogToBrowserConsole;
using mozilla::Telemetry::Common::GetNameForProcessID;
using mozilla::Telemetry::ScalarActionType;
+using mozilla::Telemetry::ScalarID;
using mozilla::Telemetry::ScalarVariant;
using mozilla::Telemetry::ProcessID;
namespace TelemetryIPCAccumulator = mozilla::TelemetryIPCAccumulator;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
@@ -2322,8 +2323,48 @@ TelemetryScalar::UpdateChildKeyedData(Pr
scalar->SetMaximum(NS_ConvertUTF8toUTF16(upd.mKey), upd.mData->as<uint32_t>());
break;
}
default:
NS_WARNING("Unsupported action coming from keyed scalar child updates.");
}
}
}
+
+void
+TelemetryScalar::RecordDiscardedData(ProcessID aProcessType,
+ const mozilla::Telemetry::DiscardedData& aDiscardedData)
+{
+ MOZ_ASSERT(XRE_IsParentProcess(),
+ "Discarded Data must be updated from the parent process.");
+ StaticMutexAutoLock locker(gTelemetryScalarsMutex);
+ if (!internal_CanRecordBase()) {
+ return;
+ }
+
+ ScalarBase* scalar = nullptr;
+ mozilla::DebugOnly<nsresult> rv;
+
+ rv = internal_GetScalarByEnum(ScalarID::TELEMETRY_DISCARDED_ACCUMULATIONS,
+ aProcessType, &scalar);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ scalar->AddValue(aDiscardedData.mDiscardedAccumulations);
+
+ rv = internal_GetScalarByEnum(ScalarID::TELEMETRY_DISCARDED_KEYED_ACCUMULATIONS,
+ aProcessType, &scalar);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ scalar->AddValue(aDiscardedData.mDiscardedKeyedAccumulations);
+
+ rv = internal_GetScalarByEnum(ScalarID::TELEMETRY_DISCARDED_SCALAR_ACTIONS,
+ aProcessType, &scalar);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ scalar->AddValue(aDiscardedData.mDiscardedScalarActions);
+
+ rv = internal_GetScalarByEnum(ScalarID::TELEMETRY_DISCARDED_KEYED_SCALAR_ACTIONS,
+ aProcessType, &scalar);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ scalar->AddValue(aDiscardedData.mDiscardedKeyedScalarActions);
+
+ rv = internal_GetScalarByEnum(ScalarID::TELEMETRY_DISCARDED_CHILD_EVENTS,
+ aProcessType, &scalar);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ scalar->AddValue(aDiscardedData.mDiscardedChildEvents);
+}
--- a/toolkit/components/telemetry/TelemetryScalar.h
+++ b/toolkit/components/telemetry/TelemetryScalar.h
@@ -62,11 +62,14 @@ size_t GetMapShallowSizesOfExcludingThis
size_t GetScalarSizesOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
void UpdateChildData(mozilla::Telemetry::ProcessID aProcessType,
const nsTArray<mozilla::Telemetry::ScalarAction>& aScalarActions);
void UpdateChildKeyedData(mozilla::Telemetry::ProcessID aProcessType,
const nsTArray<mozilla::Telemetry::KeyedScalarAction>& aScalarActions);
+void RecordDiscardedData(mozilla::Telemetry::ProcessID aProcessType,
+ const mozilla::Telemetry::DiscardedData& aDiscardedData);
+
} // namespace TelemetryScalar
#endif // TelemetryScalar_h__
--- a/toolkit/components/telemetry/ipc/TelemetryComms.h
+++ b/toolkit/components/telemetry/ipc/TelemetryComms.h
@@ -69,16 +69,24 @@ struct ChildEventData {
mozilla::TimeStamp timestamp;
nsCString category;
nsCString method;
nsCString object;
mozilla::Maybe<nsCString> value;
nsTArray<EventExtraEntry> extra;
};
+struct DiscardedData {
+ uint32_t mDiscardedAccumulations;
+ uint32_t mDiscardedKeyedAccumulations;
+ uint32_t mDiscardedScalarActions;
+ uint32_t mDiscardedKeyedScalarActions;
+ uint32_t mDiscardedChildEvents;
+};
+
} // namespace Telemetry
} // namespace mozilla
namespace IPC {
template<>
struct
ParamTraits<mozilla::Telemetry::Accumulation>
@@ -352,11 +360,17 @@ ParamTraits<mozilla::Telemetry::EventExt
!ReadParam(aMsg, aIter, &(aResult->value))) {
return false;
}
return true;
}
};
+template<>
+struct
+ParamTraits<mozilla::Telemetry::DiscardedData>
+ : public PlainOldDataSerializer<mozilla::Telemetry::DiscardedData>
+{ };
+
} // namespace IPC
#endif // Telemetry_Comms_h__
--- a/toolkit/components/telemetry/ipc/TelemetryIPC.cpp
+++ b/toolkit/components/telemetry/ipc/TelemetryIPC.cpp
@@ -40,9 +40,15 @@ TelemetryIPC::UpdateChildKeyedScalars(Te
}
void
TelemetryIPC::RecordChildEvents(Telemetry::ProcessID aProcessType, const nsTArray<Telemetry::ChildEventData>& aEvents)
{
TelemetryEvent::RecordChildEvents(aProcessType, aEvents);
}
+void
+TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID aProcessType,
+ const Telemetry::DiscardedData& aDiscardedData)
+{
+ TelemetryScalar::RecordDiscardedData(aProcessType, aDiscardedData);
}
+}
--- a/toolkit/components/telemetry/ipc/TelemetryIPC.h
+++ b/toolkit/components/telemetry/ipc/TelemetryIPC.h
@@ -17,16 +17,17 @@
namespace mozilla {
namespace Telemetry {
struct Accumulation;
struct KeyedAccumulation;
struct ScalarAction;
struct KeyedScalarAction;
struct ChildEventData;
+struct DiscardedData;
}
namespace TelemetryIPC {
/**
* Accumulate child process data into histograms for the given process type.
*
@@ -67,12 +68,21 @@ void UpdateChildKeyedScalars(Telemetry::
* 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(Telemetry::ProcessID aProcessType,
const nsTArray<Telemetry::ChildEventData>& aEvents);
+/**
+ * Record the counts of data the child process had to discard
+ *
+ * @param aProcessType - the process reporting the discarded data
+ * @param aDiscardedData - stats about the discarded data
+ */
+void RecordDiscardedData(Telemetry::ProcessID aProcessType,
+ const Telemetry::DiscardedData& aDiscardedData);
+
}
}
#endif // TelemetryIPC_h__
--- a/toolkit/components/telemetry/ipc/TelemetryIPCAccumulator.cpp
+++ b/toolkit/components/telemetry/ipc/TelemetryIPCAccumulator.cpp
@@ -20,16 +20,17 @@
#include "TelemetryScalar.h"
using mozilla::StaticMutex;
using mozilla::StaticMutexAutoLock;
using mozilla::StaticAutoPtr;
using mozilla::SystemGroup;
using mozilla::TaskCategory;
using mozilla::Telemetry::Accumulation;
+using mozilla::Telemetry::DiscardedData;
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;
@@ -43,16 +44,22 @@ const uint32_t kBatchTimeoutMs = 2000;
// To stop growing unbounded in memory while waiting for kBatchTimeoutMs to
// drain the probe accumulation arrays, we request an immediate flush if the
// arrays manage to reach certain high water mark of elements.
const size_t kHistogramAccumulationsArrayHighWaterMark = 5 * 1024;
const size_t kScalarActionsArrayHighWaterMark = 10000;
// With the current limits, events cost us about 1100 bytes each.
// This limits memory use to about 10MB.
const size_t kEventsArrayHighWaterMark = 10000;
+// If we are starved we can overshoot the watermark.
+// This is the multiplier over which we will discard data.
+const size_t kWaterMarkDiscardFactor = 5;
+
+// Counts of how many pieces of data we have discarded.
+DiscardedData gDiscardedData = {0};
// This timer is used 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.
StaticAutoPtr<nsTArray<Accumulation>> gHistogramAccumulations;
@@ -133,47 +140,62 @@ DispatchIPCTimerFired()
void
TelemetryIPCAccumulator::AccumulateChildHistogram(mozilla::Telemetry::HistogramID aId,
uint32_t aSample)
{
StaticMutexAutoLock locker(gTelemetryIPCAccumulatorMutex);
if (!gHistogramAccumulations) {
gHistogramAccumulations = new nsTArray<Accumulation>();
}
+ if (gHistogramAccumulations->Length() >=
+ kWaterMarkDiscardFactor * kHistogramAccumulationsArrayHighWaterMark) {
+ gDiscardedData.mDiscardedAccumulations++;
+ return;
+ }
if (gHistogramAccumulations->Length() == kHistogramAccumulationsArrayHighWaterMark) {
DispatchIPCTimerFired();
}
gHistogramAccumulations->AppendElement(Accumulation{aId, aSample});
ArmIPCTimer(locker);
}
void
TelemetryIPCAccumulator::AccumulateChildKeyedHistogram(mozilla::Telemetry::HistogramID aId,
const nsCString& aKey, uint32_t aSample)
{
StaticMutexAutoLock locker(gTelemetryIPCAccumulatorMutex);
if (!gKeyedHistogramAccumulations) {
gKeyedHistogramAccumulations = new nsTArray<KeyedAccumulation>();
}
+ if (gKeyedHistogramAccumulations->Length() >=
+ kWaterMarkDiscardFactor * kHistogramAccumulationsArrayHighWaterMark) {
+ gDiscardedData.mDiscardedKeyedAccumulations++;
+ return;
+ }
if (gKeyedHistogramAccumulations->Length() == kHistogramAccumulationsArrayHighWaterMark) {
DispatchIPCTimerFired();
}
gKeyedHistogramAccumulations->AppendElement(KeyedAccumulation{aId, aSample, aKey});
ArmIPCTimer(locker);
}
void
TelemetryIPCAccumulator::RecordChildScalarAction(mozilla::Telemetry::ScalarID aId,
ScalarActionType aAction, const ScalarVariant& aValue)
{
StaticMutexAutoLock locker(gTelemetryIPCAccumulatorMutex);
// Make sure to have the storage.
if (!gChildScalarsActions) {
gChildScalarsActions = new nsTArray<ScalarAction>();
}
+ if (gChildScalarsActions->Length() >=
+ kWaterMarkDiscardFactor * kScalarActionsArrayHighWaterMark) {
+ gDiscardedData.mDiscardedScalarActions++;
+ return;
+ }
if (gChildScalarsActions->Length() == kScalarActionsArrayHighWaterMark) {
DispatchIPCTimerFired();
}
// Store the action.
gChildScalarsActions->AppendElement(ScalarAction{aId, aAction, Some(aValue)});
ArmIPCTimer(locker);
}
@@ -183,16 +205,21 @@ TelemetryIPCAccumulator::RecordChildKeye
ScalarActionType aAction,
const ScalarVariant& aValue)
{
StaticMutexAutoLock locker(gTelemetryIPCAccumulatorMutex);
// Make sure to have the storage.
if (!gChildKeyedScalarsActions) {
gChildKeyedScalarsActions = new nsTArray<KeyedScalarAction>();
}
+ if (gChildKeyedScalarsActions->Length() >=
+ kWaterMarkDiscardFactor * kScalarActionsArrayHighWaterMark) {
+ gDiscardedData.mDiscardedKeyedScalarActions++;
+ return;
+ }
if (gChildKeyedScalarsActions->Length() == kScalarActionsArrayHighWaterMark) {
DispatchIPCTimerFired();
}
// Store the action.
gChildKeyedScalarsActions->AppendElement(
KeyedScalarAction{aId, aAction, NS_ConvertUTF16toUTF8(aKey), Some(aValue)});
ArmIPCTimer(locker);
}
@@ -206,16 +233,22 @@ TelemetryIPCAccumulator::RecordChildEven
const nsTArray<mozilla::Telemetry::EventExtraEntry>& extra)
{
StaticMutexAutoLock locker(gTelemetryIPCAccumulatorMutex);
if (!gChildEvents) {
gChildEvents = new nsTArray<ChildEventData>();
}
+ if (gChildEvents->Length() >=
+ kWaterMarkDiscardFactor * kEventsArrayHighWaterMark) {
+ gDiscardedData.mDiscardedChildEvents++;
+ return;
+ }
+
if (gChildEvents->Length() == kEventsArrayHighWaterMark) {
DispatchIPCTimerFired();
}
// Store the event.
gChildEvents->AppendElement(ChildEventData{timestamp, nsCString(category),
nsCString(method), nsCString(object),
value,
@@ -231,35 +264,37 @@ 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;
+ DiscardedData discardedData;
{
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);
}
+ discardedData = gDiscardedData;
+ gDiscardedData = {0};
}
// 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));
}
@@ -274,16 +309,18 @@ SendAccumulatedData(TActor* ipcActor)
if (keyedScalarsToSend.Length()) {
mozilla::Unused <<
NS_WARN_IF(!ipcActor->SendUpdateChildKeyedScalars(keyedScalarsToSend));
}
if (eventsToSend.Length()) {
mozilla::Unused <<
NS_WARN_IF(!ipcActor->SendRecordChildEvents(eventsToSend));
}
+ mozilla::Unused <<
+ NS_WARN_IF(!ipcActor->SendRecordDiscardedData(discardedData));
}
// 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