Bug 1235858: Record the time stamp, use it for crash reports. r?botond draft
authorMilan Sreckovic <milan@mozilla.com>
Wed, 30 Dec 2015 13:55:31 -0500
changeset 318060 d9e39a5ef8224b58661cd95d711b5523388fb212
parent 317879 9ddf0da90fb3bc1ae29966dc596013fc54a44bd2
child 512409 603b5379f4acbaf342c9412bb520c0215f9ab3f1
push id8820
push usermsreckovic@mozilla.com
push dateWed, 30 Dec 2015 18:55:51 +0000
reviewersbotond
bugs1235858
milestone46.0a1
Bug 1235858: Record the time stamp, use it for crash reports. r?botond
gfx/2d/Logging.h
gfx/thebes/gfxPlatform.cpp
widget/GfxInfoBase.cpp
--- a/gfx/2d/Logging.h
+++ b/gfx/2d/Logging.h
@@ -9,16 +9,17 @@
 #include <string>
 #include <sstream>
 #include <stdio.h>
 #include <vector>
 
 #ifdef MOZ_LOGGING
 #include "mozilla/Logging.h"
 #endif
+#include "mozilla/Tuple.h"
 
 #if defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)
 #include "nsDebug.h"
 #endif
 #include "Point.h"
 #include "BaseRect.h"
 #include "Matrix.h"
 
@@ -217,27 +218,29 @@ struct BasicLogger
 
 struct CriticalLogger {
   static void OutputMessage(const std::string &aString, int aLevel, bool aNoNewline);
   static void CrashAction(LogReason aReason);
 };
 
 // Implement this interface and init the Factory with an instance to
 // forward critical logs.
+typedef mozilla::Tuple<int32_t,std::string,double> LoggingRecordEntry;
+typedef std::vector<LoggingRecordEntry> LoggingRecord;
 class LogForwarder {
 public:
   virtual ~LogForwarder() {}
   virtual void Log(const std::string &aString) = 0;
   virtual void CrashAction(LogReason aReason) = 0;
 
   // Provide a copy of the logs to the caller.  The int is the index
   // of the Log call, if the number of logs exceeds some preset capacity
   // we may not get all of them, so the indices help figure out which
-  // ones we did save.
-  virtual std::vector<std::pair<int32_t,std::string> > StringsVectorCopy() = 0;
+  // ones we did save.  double is the timestamp in seconds.
+  virtual LoggingRecord StringsVectorCopy() = 0;
 };
 
 class NoLog
 {
 public:
   NoLog() {}
   ~NoLog() {}
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -185,27 +185,27 @@ public:
 
 class CrashStatsLogForwarder: public mozilla::gfx::LogForwarder
 {
 public:
   explicit CrashStatsLogForwarder(const char* aKey);
   virtual void Log(const std::string& aString) override;
   virtual void CrashAction(LogReason aReason) override;
 
-  virtual std::vector<std::pair<int32_t,std::string> > StringsVectorCopy() override;
+  virtual LoggingRecord StringsVectorCopy() override;
 
   void SetCircularBufferSize(uint32_t aCapacity);
 
 private:
   // Helpers for the Log()
-  bool UpdateStringsVector(const std::string& aString);
+  bool UpdateStringsVector(const std::string& aString, bool aStampTime);
   void UpdateCrashReport();
 
 private:
-  std::vector<std::pair<int32_t,std::string> > mBuffer;
+  LoggingRecord mBuffer;
   nsCString mCrashCriticalKey;
   uint32_t mMaxCapacity;
   int32_t mIndex;
   Mutex mMutex;
 };
 
 CrashStatsLogForwarder::CrashStatsLogForwarder(const char* aKey)
   : mBuffer()
@@ -219,55 +219,60 @@ CrashStatsLogForwarder::CrashStatsLogFor
 void CrashStatsLogForwarder::SetCircularBufferSize(uint32_t aCapacity)
 {
   MutexAutoLock lock(mMutex);
 
   mMaxCapacity = aCapacity;
   mBuffer.reserve(static_cast<size_t>(aCapacity));
 }
 
-std::vector<std::pair<int32_t,std::string> >
+LoggingRecord
 CrashStatsLogForwarder::StringsVectorCopy()
 {
   MutexAutoLock lock(mMutex);
   return mBuffer;
 }
 
 bool
-CrashStatsLogForwarder::UpdateStringsVector(const std::string& aString)
+CrashStatsLogForwarder::UpdateStringsVector(const std::string& aString, bool aStampTime)
 {
   // We want at least the first one and the last one.  Otherwise, no point.
   if (mMaxCapacity < 2) {
     return false;
   }
 
   mIndex += 1;
   MOZ_ASSERT(mIndex >= 0);
 
   // index will count 0, 1, 2, ..., max-1, 1, 2, ..., max-1, 1, 2, ...
   int32_t index = mIndex ? (mIndex-1) % (mMaxCapacity-1) + 1 : 0;
   MOZ_ASSERT(index >= 0 && index < (int32_t)mMaxCapacity);
   MOZ_ASSERT(index <= mIndex && index <= (int32_t)mBuffer.size());
 
-  // Checking for index >= mBuffer.size(), rather than index == mBuffer.size()
+ // Checking for index >= mBuffer.size(), rather than index == mBuffer.size()
   // just out of paranoia, but we know index <= mBuffer.size().
-  std::pair<int32_t,std::string> newEntry(mIndex,aString);
+  double tStamp = 0.0;
+  if (aStampTime) {
+    bool ignored;
+    tStamp = (TimeStamp::NowLoRes()-TimeStamp::ProcessCreation(ignored)).ToSecondsSigDigits();
+  }
+  LoggingRecordEntry newEntry(mIndex,aString,tStamp);
   if (index >= static_cast<int32_t>(mBuffer.size())) {
     mBuffer.push_back(newEntry);
   } else {
     mBuffer[index] = newEntry;
   }
   return true;
 }
 
 void CrashStatsLogForwarder::UpdateCrashReport()
 {
   std::stringstream message;
-  for(std::vector<std::pair<int32_t, std::string> >::iterator it = mBuffer.begin(); it != mBuffer.end(); ++it) {
-    message << "|[" << (*it).first << "]" << (*it).second;
+  for(LoggingRecord::iterator it = mBuffer.begin(); it != mBuffer.end(); ++it) {
+    message << "|[" << Get<0>(*it) << "]" << Get<1>(*it) << " (t=" << Get<2>(*it) << ")";
   }
 
 #ifdef MOZ_CRASHREPORTER
   nsCString reportString(message.str().c_str());
   nsresult annotated = CrashReporter::AnnotateCrashReport(mCrashCriticalKey, reportString);
 #else
   nsresult annotated = NS_ERROR_NOT_IMPLEMENTED;
 #endif
@@ -276,17 +281,17 @@ void CrashStatsLogForwarder::UpdateCrash
            mCrashCriticalKey.get(), message.str().c_str());
   }
 }
 
 void CrashStatsLogForwarder::Log(const std::string& aString)
 {
   MutexAutoLock lock(mMutex);
 
-  if (UpdateStringsVector(aString)) {
+  if (UpdateStringsVector(aString, true)) {
     UpdateCrashReport();
   }
 }
 
 class CrashTelemetryEvent : public nsRunnable
 {
   virtual ~CrashTelemetryEvent() {}
 
@@ -415,16 +420,18 @@ MemoryPressureObserver::Observe(nsISuppo
     NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic");
     Factory::PurgeAllCaches();
     gfxGradientCache::PurgeAllCaches();
 
     gfxPlatform::GetPlatform()->PurgeSkiaCache();
     return NS_OK;
 }
 
+#include "mozilla/TimeStamp.h"
+
 gfxPlatform::gfxPlatform()
   : mTileWidth(-1)
   , mTileHeight(-1)
   , mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
   , mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo)
   , mCompositorBackend(layers::LayersBackend::LAYERS_NONE)
   , mScreenDepth(0)
 {
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -1070,17 +1070,17 @@ NS_IMETHODIMP GfxInfoBase::GetFailures(u
     return NS_ERROR_UNEXPECTED;
   }
 
   // There are two stirng copies in this method, starting with this one. We are
   // assuming this is not a big deal, as the size of the array should be small
   // and the strings in it should be small as well (the error messages in the
   // code.)  The second copy happens with the Clone() calls.  Technically,
   // we don't need the mutex lock after the StringVectorCopy() call.
-  std::vector<std::pair<int32_t,std::string> > loggedStrings = logForwarder->StringsVectorCopy();
+  LoggingRecord loggedStrings = logForwarder->StringsVectorCopy();
   *failureCount = loggedStrings.size();
 
   if (*failureCount != 0) {
     *failures = (char**)moz_xmalloc(*failureCount * sizeof(char*));
     if (!(*failures)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     if (indices) {
@@ -1088,21 +1088,21 @@ NS_IMETHODIMP GfxInfoBase::GetFailures(u
       if (!(*indices)) {
         free(*failures);
         *failures = nullptr;
         return NS_ERROR_OUT_OF_MEMORY;
       }
     }
 
     /* copy over the failure messages into the array we just allocated */
-    std::vector<std::pair<int32_t, std::string> >::const_iterator it;
+    LoggingRecord::const_iterator it;
     uint32_t i=0;
     for(it = loggedStrings.begin() ; it != loggedStrings.end(); ++it, i++) {
-      (*failures)[i] = (char*)nsMemory::Clone((*it).second.c_str(), (*it).second.size() + 1);
-      if (indices) (*indices)[i] = (*it).first;
+      (*failures)[i] = (char*)nsMemory::Clone(Get<1>(*it).c_str(), Get<1>(*it).size() + 1);
+      if (indices) (*indices)[i] = Get<0>(*it);
 
       if (!(*failures)[i]) {
         /* <sarcasm> I'm too afraid to use an inline function... </sarcasm> */
         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, (*failures));
         *failureCount = i;
         return NS_ERROR_OUT_OF_MEMORY;
       }
     }