michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef Telemetry_h__ michael@0: #define Telemetry_h__ michael@0: michael@0: #include "mozilla/GuardObjects.h" michael@0: #include "mozilla/TimeStamp.h" michael@0: #include "mozilla/StartupTimeline.h" michael@0: #include "nsTArray.h" michael@0: #include "nsStringGlue.h" michael@0: michael@0: namespace base { michael@0: class Histogram; michael@0: } michael@0: michael@0: namespace mozilla { michael@0: namespace Telemetry { michael@0: michael@0: #include "TelemetryHistogramEnums.h" michael@0: michael@0: enum TimerResolution { michael@0: Millisecond, michael@0: Microsecond michael@0: }; michael@0: michael@0: /** michael@0: * Initialize the Telemetry service on the main thread at startup. michael@0: */ michael@0: void Init(); michael@0: michael@0: /** michael@0: * Adds sample to a histogram defined in TelemetryHistograms.h michael@0: * michael@0: * @param id - histogram id michael@0: * @param sample - value to record. michael@0: */ michael@0: void Accumulate(ID id, uint32_t sample); michael@0: michael@0: /** michael@0: * Adds a sample to a histogram defined in TelemetryHistograms.h. michael@0: * This function is here to support telemetry measurements from Java, michael@0: * where we have only names and not numeric IDs. You should almost michael@0: * certainly be using the by-enum-id version instead of this one. michael@0: * michael@0: * @param name - histogram name michael@0: * @param sample - value to record michael@0: */ michael@0: void Accumulate(const char* name, uint32_t sample); michael@0: michael@0: /** michael@0: * Adds time delta in milliseconds to a histogram defined in TelemetryHistograms.h michael@0: * michael@0: * @param id - histogram id michael@0: * @param start - start time michael@0: * @param end - end time michael@0: */ michael@0: void AccumulateTimeDelta(ID id, TimeStamp start, TimeStamp end = TimeStamp::Now()); michael@0: michael@0: /** michael@0: * Return a raw Histogram for direct manipulation for users who can not use Accumulate(). michael@0: */ michael@0: base::Histogram* GetHistogramById(ID id); michael@0: michael@0: /** michael@0: * Those wrappers are needed because the VS versions we use do not support free michael@0: * functions with default template arguments. michael@0: */ michael@0: template michael@0: struct AccumulateDelta_impl michael@0: { michael@0: static void compute(ID id, TimeStamp start, TimeStamp end = TimeStamp::Now()); michael@0: }; michael@0: michael@0: template<> michael@0: struct AccumulateDelta_impl michael@0: { michael@0: static void compute(ID id, TimeStamp start, TimeStamp end = TimeStamp::Now()) { michael@0: Accumulate(id, static_cast((end - start).ToMilliseconds())); michael@0: } michael@0: }; michael@0: michael@0: template<> michael@0: struct AccumulateDelta_impl michael@0: { michael@0: static void compute(ID id, TimeStamp start, TimeStamp end = TimeStamp::Now()) { michael@0: Accumulate(id, static_cast((end - start).ToMicroseconds())); michael@0: } michael@0: }; michael@0: michael@0: michael@0: template michael@0: class AutoTimer { michael@0: public: michael@0: AutoTimer(TimeStamp aStart = TimeStamp::Now() MOZ_GUARD_OBJECT_NOTIFIER_PARAM) michael@0: : start(aStart) michael@0: { michael@0: MOZ_GUARD_OBJECT_NOTIFIER_INIT; michael@0: } michael@0: michael@0: ~AutoTimer() { michael@0: AccumulateDelta_impl::compute(id, start); michael@0: } michael@0: michael@0: private: michael@0: const TimeStamp start; michael@0: MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER michael@0: }; michael@0: michael@0: template michael@0: class AutoCounter { michael@0: public: michael@0: AutoCounter(uint32_t counterStart = 0 MOZ_GUARD_OBJECT_NOTIFIER_PARAM) michael@0: : counter(counterStart) michael@0: { michael@0: MOZ_GUARD_OBJECT_NOTIFIER_INIT; michael@0: } michael@0: michael@0: ~AutoCounter() { michael@0: Accumulate(id, counter); michael@0: } michael@0: michael@0: // Prefix increment only, to encourage good habits. michael@0: void operator++() { michael@0: ++counter; michael@0: } michael@0: michael@0: // Chaining doesn't make any sense, don't return anything. michael@0: void operator+=(int increment) { michael@0: counter += increment; michael@0: } michael@0: michael@0: private: michael@0: uint32_t counter; michael@0: MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER michael@0: }; michael@0: michael@0: /** michael@0: * Indicates whether Telemetry recording is turned on. This is intended michael@0: * to guard calls to Accumulate when the statistic being recorded is michael@0: * expensive to compute. michael@0: */ michael@0: bool CanRecord(); michael@0: michael@0: /** michael@0: * Records slow SQL statements for Telemetry reporting. michael@0: * michael@0: * @param statement - offending SQL statement to record michael@0: * @param dbName - DB filename michael@0: * @param delay - execution time in milliseconds michael@0: */ michael@0: void RecordSlowSQLStatement(const nsACString &statement, michael@0: const nsACString &dbName, michael@0: uint32_t delay); michael@0: michael@0: /** michael@0: * Initialize I/O Reporting michael@0: * Initially this only records I/O for files in the binary directory. michael@0: * michael@0: * @param aXreDir - XRE directory michael@0: */ michael@0: void InitIOReporting(nsIFile* aXreDir); michael@0: michael@0: /** michael@0: * Set the profile directory. Once called, files in the profile directory will michael@0: * be included in I/O reporting. We can't use the directory michael@0: * service to obtain this information because it isn't running yet. michael@0: */ michael@0: void SetProfileDir(nsIFile* aProfD); michael@0: michael@0: /** michael@0: * Called to inform Telemetry that startup has completed. michael@0: */ michael@0: void LeavingStartupStage(); michael@0: michael@0: /** michael@0: * Called to inform Telemetry that shutdown is commencing. michael@0: */ michael@0: void EnteringShutdownStage(); michael@0: michael@0: /** michael@0: * Thresholds for a statement to be considered slow, in milliseconds michael@0: */ michael@0: const uint32_t kSlowSQLThresholdForMainThread = 50; michael@0: const uint32_t kSlowSQLThresholdForHelperThreads = 100; michael@0: michael@0: class ProcessedStack; michael@0: michael@0: /** michael@0: * Record the main thread's call stack after it hangs. michael@0: * michael@0: * @param aDuration - Approximate duration of main thread hang, in seconds michael@0: * @param aStack - Array of PCs from the hung call stack michael@0: * @param aSystemUptime - System uptime at the time of the hang, in minutes michael@0: * @param aFirefoxUptime - Firefox uptime at the time of the hang, in minutes michael@0: */ michael@0: #if defined(MOZ_ENABLE_PROFILER_SPS) michael@0: void RecordChromeHang(uint32_t aDuration, michael@0: ProcessedStack &aStack, michael@0: int32_t aSystemUptime, michael@0: int32_t aFirefoxUptime); michael@0: #endif michael@0: michael@0: class ThreadHangStats; michael@0: michael@0: /** michael@0: * Move a ThreadHangStats to Telemetry storage. Normally Telemetry queries michael@0: * for active ThreadHangStats through BackgroundHangMonitor, but once a michael@0: * thread exits, the thread's copy of ThreadHangStats needs to be moved to michael@0: * inside Telemetry using this function. michael@0: * michael@0: * @param aStats ThreadHangStats to save; the data inside aStats michael@0: * will be moved and aStats should be treated as michael@0: * invalid after this function returns michael@0: */ michael@0: void RecordThreadHangStats(ThreadHangStats& aStats); michael@0: michael@0: /** michael@0: * Record a failed attempt at locking the user's profile. michael@0: * michael@0: * @param aProfileDir The profile directory whose lock attempt failed michael@0: */ michael@0: void WriteFailedProfileLock(nsIFile* aProfileDir); michael@0: michael@0: } // namespace Telemetry michael@0: } // namespace mozilla michael@0: #endif // Telemetry_h__