Bug 1235858: Record the time stamp, use it for crash reports. r?botond
--- 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;
}
}