mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 814765 - Include late writes in the Telemetry ping. r=vladan.
--HG-- extra : rebase_source : d3863b0ef7f4f77411042c374227d9f41adda929
This commit is contained in:
parent
92a0820a3a
commit
6adb826fe4
@ -50,6 +50,8 @@ CPPSRCS = \
|
||||
Telemetry.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
|
||||
|
||||
EXTRA_DSO_LDOPTS += \
|
||||
$(MOZ_COMPONENT_LIBS) \
|
||||
$(MOZ_JS_LIBS) \
|
||||
|
@ -5,6 +5,12 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef XP_MACOS
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
||||
#include <prio.h>
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Likely.h"
|
||||
@ -15,6 +21,7 @@
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXPCOMPrivate.h"
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "mozilla/Services.h"
|
||||
@ -304,6 +311,7 @@ private:
|
||||
static bool AddonReflector(AddonEntryType *entry, JSContext *cx, JSObject *obj);
|
||||
static bool CreateHistogramForAddon(const nsACString &name,
|
||||
AddonHistogramInfo &info);
|
||||
void ReadLateWritesStacks();
|
||||
AddonMapType mAddonMap;
|
||||
|
||||
// This is used for speedy string->Telemetry::ID conversions
|
||||
@ -322,6 +330,7 @@ private:
|
||||
Mutex mHangReportsMutex;
|
||||
nsIMemoryReporter *mMemoryReporter;
|
||||
|
||||
CombinedStacks mLateWritesStacks; // This is collected out of the main thread.
|
||||
bool mCachedTelemetryData;
|
||||
uint32_t mLastShutdownTime;
|
||||
nsCOMArray<nsIFetchTelemetryDataCallback> mCallbacks;
|
||||
@ -738,6 +747,7 @@ public:
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
mTelemetry->mLastShutdownTime = ReadLastShutdownDuration(mFilename);
|
||||
mTelemetry->ReadLateWritesStacks();
|
||||
nsCOMPtr<nsIRunnable> e =
|
||||
NS_NewRunnableMethod(this, &nsFetchTelemetryData::MainThread);
|
||||
NS_ENSURE_STATE(e);
|
||||
@ -1533,6 +1543,150 @@ CreateJSStackObject(JSContext *cx, const CombinedStacks &stacks) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Read a stack from the given file name. In case of any error, aStack is
|
||||
// unchanged.
|
||||
static void
|
||||
ReadStack(const char *aFileName, Telemetry::ProcessedStack &aStack)
|
||||
{
|
||||
#ifdef XP_MACOS
|
||||
std::ifstream file(aFileName);
|
||||
|
||||
size_t numModules;
|
||||
file >> numModules;
|
||||
if (file.fail()) {
|
||||
return;
|
||||
}
|
||||
|
||||
char newline = file.get();
|
||||
if (file.fail() || newline != '\n') {
|
||||
return;
|
||||
}
|
||||
|
||||
Telemetry::ProcessedStack stack;
|
||||
for (size_t i = 0; i < numModules; ++i) {
|
||||
std::string moduleName;
|
||||
getline(file, moduleName);
|
||||
if (file.fail()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Telemetry::ProcessedStack::Module module = {
|
||||
moduleName,
|
||||
0, // mPdbAge
|
||||
"", // mPdbSignature
|
||||
"" // mPdbName
|
||||
};
|
||||
stack.AddModule(module);
|
||||
}
|
||||
|
||||
size_t numFrames;
|
||||
file >> numFrames;
|
||||
if (file.fail()) {
|
||||
return;
|
||||
}
|
||||
|
||||
newline = file.get();
|
||||
if (file.fail() || newline != '\n') {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numFrames; ++i) {
|
||||
uint16_t index;
|
||||
file >> index;
|
||||
uintptr_t offset;
|
||||
file >> std::hex >> offset >> std::dec;
|
||||
if (file.fail()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Telemetry::ProcessedStack::Frame frame = {
|
||||
offset,
|
||||
index
|
||||
};
|
||||
stack.AddFrame(frame);
|
||||
}
|
||||
|
||||
aStack = stack;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
TelemetryImpl::ReadLateWritesStacks()
|
||||
{
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(profileDir));
|
||||
if (!profileDir || NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString nativePath;
|
||||
rv = profileDir->GetNativePath(nativePath);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = nativePath.get();
|
||||
PRDir *dir = PR_OpenDir(name);
|
||||
if (!dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
PRDirEntry *ent;
|
||||
const char *prefix = "Telemetry.LateWriteFinal-";
|
||||
unsigned int prefixLen = strlen(prefix);
|
||||
while ((ent = PR_ReadDir(dir, PR_SKIP_NONE))) {
|
||||
if (strncmp(prefix, ent->name, prefixLen) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoCString stackNativePath = nativePath;
|
||||
stackNativePath += XPCOM_FILE_PATH_SEPARATOR;
|
||||
stackNativePath += nsDependentCString(ent->name);
|
||||
|
||||
Telemetry::ProcessedStack stack;
|
||||
ReadStack(stackNativePath.get(), stack);
|
||||
if (stack.GetStackSize() != 0) {
|
||||
mLateWritesStacks.AddStack(stack);
|
||||
}
|
||||
// Delete the file so that we don't report it again on the next run.
|
||||
PR_Delete(stackNativePath.get());
|
||||
}
|
||||
PR_CloseDir(dir);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::GetLateWrites(JSContext *cx, jsval *ret)
|
||||
{
|
||||
// The user must call AsyncReadTelemetryData first. We return an empty list
|
||||
// instead of reporting a failure so that the rest of telemetry can uniformly
|
||||
// handle the read not being available yet.
|
||||
|
||||
// FIXME: we allocate the js object again and again in the getter. We should
|
||||
// figure out a way to cache it. In order to do that we have to call
|
||||
// JS_AddNamedObjectRoot. A natural place to do so is in the TelemetryImpl
|
||||
// constructor, but it is not clear how to get a JSContext in there.
|
||||
// Another option would be to call it in here when we first call
|
||||
// CreateJSStackObject, but we would still need to figure out where to call
|
||||
// JS_RemoveObjectRoot. Would it be ok to never call JS_RemoveObjectRoot
|
||||
// and just set the pointer to nullptr is the telemetry destructor?
|
||||
|
||||
JSObject *report;
|
||||
if (!mCachedTelemetryData) {
|
||||
CombinedStacks empty;
|
||||
report = CreateJSStackObject(cx, empty);
|
||||
} else {
|
||||
report = CreateJSStackObject(cx, mLateWritesStacks);
|
||||
}
|
||||
|
||||
if (report == nullptr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*ret = OBJECT_TO_JSVAL(report);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::GetRegisteredHistograms(JSContext *cx, jsval *ret)
|
||||
{
|
||||
|
@ -518,6 +518,7 @@ TelemetryPing.prototype = {
|
||||
histograms: this.getHistograms(Telemetry.histogramSnapshots),
|
||||
slowSQL: Telemetry.slowSQL,
|
||||
chromeHangs: Telemetry.chromeHangs,
|
||||
lateWrites: Telemetry.lateWrites,
|
||||
addonHistograms: this.getAddonHistograms()
|
||||
};
|
||||
|
||||
|
@ -87,6 +87,18 @@ interface nsITelemetry : nsISupports
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval chromeHangs;
|
||||
|
||||
/*
|
||||
* An object with two fields: memoryMap and stacks.
|
||||
* * memoryMap is a list of loaded libraries.
|
||||
* * stacks is a list of stacks. Each stack is a list of pairs of the form
|
||||
* [moduleIndex, offset]. The moduleIndex is an index into the memoryMap and
|
||||
* offset is an offset in the library at memoryMap[moduleIndex].
|
||||
* This format is used to make it easier to send the stacks to the
|
||||
* symbolication server.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval lateWrites;
|
||||
|
||||
/**
|
||||
* An object whose properties are the names of histograms defined in
|
||||
* TelemetryHistograms.h and whose corresponding values are the textual
|
||||
@ -193,8 +205,9 @@ interface nsITelemetry : nsISupports
|
||||
readonly attribute jsval addonHistogramSnapshots;
|
||||
|
||||
/**
|
||||
* Read data from the previous run. After the callback is called, the data is
|
||||
* available in lastShutdownDuration.
|
||||
* Read data from the previous run. After the callback is called, the last
|
||||
* shutdown time is available in lastShutdownDuration and any late
|
||||
* writes in lateWrites.
|
||||
*/
|
||||
void asyncFetchTelemetryData(in nsIFetchTelemetryDataCallback aCallback);
|
||||
};
|
||||
|
@ -734,7 +734,29 @@ function onLoad() {
|
||||
|
||||
// Get the Telemetry Ping payload
|
||||
Telemetry.asyncFetchTelemetryData(displayPingData);
|
||||
}
|
||||
};
|
||||
|
||||
let LateWritesSingleton = {
|
||||
renderLateWrites: function LateWritesSingleton_renderLateWrites(lateWrites) {
|
||||
let writesDiv = document.getElementById("late-writes-data");
|
||||
clearDivData(writesDiv);
|
||||
// FIXME: Add symbolication support. Refactor with the chrome hang one.
|
||||
|
||||
let stacks = lateWrites.stacks;
|
||||
if (stacks.length == 0) {
|
||||
showEmptySectionMessage("late-writes-section");
|
||||
return;
|
||||
}
|
||||
|
||||
let memoryMap = lateWrites.memoryMap;
|
||||
StackRenderer.renderMemoryMap(writesDiv, memoryMap);
|
||||
|
||||
for (let i = 0; i < stacks.length; ++i) {
|
||||
let stack = stacks[i];
|
||||
StackRenderer.renderStack(writesDiv, stack);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function displayPingData() {
|
||||
let ping = TelemetryPing.getPayload();
|
||||
@ -746,6 +768,8 @@ function displayPingData() {
|
||||
showEmptySectionMessage("simple-measurements-section");
|
||||
}
|
||||
|
||||
LateWritesSingleton.renderLateWrites(ping.lateWrites);
|
||||
|
||||
// Show basic system info gathered
|
||||
if (Object.keys(ping.info).length) {
|
||||
KeyValueTable.render("system-info-table", ping.info);
|
||||
|
@ -81,6 +81,20 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="late-writes-section" class="data-section">
|
||||
<h1 class="section-name">&aboutTelemetry.lateWritesSection;</h1>
|
||||
<span class="toggle-caption">&aboutTelemetry.toggleOn;</span>
|
||||
<span class="toggle-caption hidden">&aboutTelemetry.toggleOff;</span>
|
||||
<span class="empty-caption hidden">&aboutTelemetry.emptySection;</span>
|
||||
<div id="late-writes" class="data hidden">
|
||||
<!-- FIXME: add fetch-symbols and hide-symbols -->
|
||||
<br/>
|
||||
<br/>
|
||||
<div id="late-writes-data">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="system-info-section" class="data-section">
|
||||
<h1 class="section-name">&aboutTelemetry.systemInfoSection;</h1>
|
||||
<span class="toggle-caption">&aboutTelemetry.toggleOn;</span>
|
||||
|
@ -28,6 +28,10 @@
|
||||
Simple Measurements
|
||||
">
|
||||
|
||||
<!ENTITY aboutTelemetry.lateWritesSection "
|
||||
Late Writes
|
||||
">
|
||||
|
||||
<!ENTITY aboutTelemetry.systemInfoSection "
|
||||
System Information
|
||||
">
|
||||
|
Loading…
Reference in New Issue
Block a user