Merge pull request #8648 from electron/set-extra-crash-reporter-data
Support updating crash reporter extra parameters
This commit is contained in:
commit
897d58bde1
12 changed files with 149 additions and 23 deletions
|
@ -31,19 +31,27 @@ struct Converter<CrashReporter::UploadReportResult> {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
void SetExtraParameter(const std::string& key, mate::Arguments* args) {
|
||||||
|
std::string value;
|
||||||
|
if (args->GetNext(&value))
|
||||||
|
CrashReporter::GetInstance()->SetExtraParameter(key, value);
|
||||||
|
else
|
||||||
|
CrashReporter::GetInstance()->RemoveExtraParameter(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||||
v8::Local<v8::Context> context, void* priv) {
|
v8::Local<v8::Context> context, void* priv) {
|
||||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||||
auto report = base::Unretained(CrashReporter::GetInstance());
|
auto reporter = base::Unretained(CrashReporter::GetInstance());
|
||||||
dict.SetMethod("start",
|
dict.SetMethod("start", base::Bind(&CrashReporter::Start, reporter));
|
||||||
base::Bind(&CrashReporter::Start, report));
|
dict.SetMethod("setExtraParameter", &SetExtraParameter);
|
||||||
dict.SetMethod("_getUploadedReports",
|
dict.SetMethod("getUploadedReports",
|
||||||
base::Bind(&CrashReporter::GetUploadedReports, report));
|
base::Bind(&CrashReporter::GetUploadedReports, reporter));
|
||||||
dict.SetMethod("_setUploadToServer",
|
dict.SetMethod("setUploadToServer",
|
||||||
base::Bind(&CrashReporter::SetUploadToServer, report));
|
base::Bind(&CrashReporter::SetUploadToServer, reporter));
|
||||||
dict.SetMethod("_getUploadToServer",
|
dict.SetMethod("getUploadToServer",
|
||||||
base::Bind(&CrashReporter::GetUploadToServer, report));
|
base::Bind(&CrashReporter::GetUploadToServer, reporter));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -86,6 +86,13 @@ void CrashReporter::InitBreakpad(const std::string& product_name,
|
||||||
void CrashReporter::SetUploadParameters() {
|
void CrashReporter::SetUploadParameters() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrashReporter::SetExtraParameter(const std::string& key,
|
||||||
|
const std::string& value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashReporter::RemoveExtraParameter(const std::string& key) {
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(OS_MACOSX) && defined(MAS_BUILD)
|
#if defined(OS_MACOSX) && defined(MAS_BUILD)
|
||||||
// static
|
// static
|
||||||
CrashReporter* CrashReporter::GetInstance() {
|
CrashReporter* CrashReporter::GetInstance() {
|
||||||
|
|
|
@ -37,6 +37,9 @@ class CrashReporter {
|
||||||
|
|
||||||
virtual void SetUploadToServer(bool upload_to_server);
|
virtual void SetUploadToServer(bool upload_to_server);
|
||||||
virtual bool GetUploadToServer();
|
virtual bool GetUploadToServer();
|
||||||
|
virtual void SetExtraParameter(const std::string& key,
|
||||||
|
const std::string& value);
|
||||||
|
virtual void RemoveExtraParameter(const std::string& key);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CrashReporter();
|
CrashReporter();
|
||||||
|
|
|
@ -64,13 +64,15 @@ void CrashReporterLinux::InitBreakpad(const std::string& product_name,
|
||||||
bool skip_system_crash_handler) {
|
bool skip_system_crash_handler) {
|
||||||
EnableCrashDumping(crashes_dir);
|
EnableCrashDumping(crashes_dir);
|
||||||
|
|
||||||
crash_keys_.SetKeyValue("prod", ATOM_PRODUCT_NAME);
|
crash_keys_.reset(new CrashKeyStorage());
|
||||||
crash_keys_.SetKeyValue("ver", version.c_str());
|
|
||||||
|
crash_keys_->SetKeyValue("prod", ATOM_PRODUCT_NAME);
|
||||||
|
crash_keys_->SetKeyValue("ver", version.c_str());
|
||||||
upload_url_ = submit_url;
|
upload_url_ = submit_url;
|
||||||
|
|
||||||
for (StringMap::const_iterator iter = upload_parameters_.begin();
|
for (StringMap::const_iterator iter = upload_parameters_.begin();
|
||||||
iter != upload_parameters_.end(); ++iter)
|
iter != upload_parameters_.end(); ++iter)
|
||||||
crash_keys_.SetKeyValue(iter->first.c_str(), iter->second.c_str());
|
crash_keys_->SetKeyValue(iter->first.c_str(), iter->second.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashReporterLinux::SetUploadParameters() {
|
void CrashReporterLinux::SetUploadParameters() {
|
||||||
|
@ -120,7 +122,7 @@ bool CrashReporterLinux::CrashDone(const MinidumpDescriptor& minidump,
|
||||||
info.oom_size = base::g_oom_size;
|
info.oom_size = base::g_oom_size;
|
||||||
info.pid = self->pid_;
|
info.pid = self->pid_;
|
||||||
info.upload_url = self->upload_url_.c_str();
|
info.upload_url = self->upload_url_.c_str();
|
||||||
info.crash_keys = &self->crash_keys_;
|
info.crash_keys = self->crash_keys_.get();
|
||||||
HandleCrashDump(info);
|
HandleCrashDump(info);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ class CrashReporterLinux : public CrashReporter {
|
||||||
const bool succeeded);
|
const bool succeeded);
|
||||||
|
|
||||||
std::unique_ptr<google_breakpad::ExceptionHandler> breakpad_;
|
std::unique_ptr<google_breakpad::ExceptionHandler> breakpad_;
|
||||||
CrashKeyStorage crash_keys_;
|
std::unique_ptr<CrashKeyStorage> crash_keys_;
|
||||||
|
|
||||||
uint64_t process_start_time_;
|
uint64_t process_start_time_;
|
||||||
pid_t pid_;
|
pid_t pid_;
|
||||||
|
|
|
@ -34,6 +34,9 @@ class CrashReporterMac : public CrashReporter {
|
||||||
void SetUploadParameters() override;
|
void SetUploadParameters() override;
|
||||||
void SetUploadToServer(bool upload_to_server) override;
|
void SetUploadToServer(bool upload_to_server) override;
|
||||||
bool GetUploadToServer() override;
|
bool GetUploadToServer() override;
|
||||||
|
void SetExtraParameter(const std::string& key,
|
||||||
|
const std::string& value) override;
|
||||||
|
void RemoveExtraParameter(const std::string& key) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct base::DefaultSingletonTraits<CrashReporterMac>;
|
friend struct base::DefaultSingletonTraits<CrashReporterMac>;
|
||||||
|
|
|
@ -100,6 +100,21 @@ void CrashReporterMac::SetCrashKeyValue(const base::StringPiece& key,
|
||||||
simple_string_dictionary_->SetKeyValue(key.data(), value.data());
|
simple_string_dictionary_->SetKeyValue(key.data(), value.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrashReporterMac::SetExtraParameter(const std::string& key,
|
||||||
|
const std::string& value) {
|
||||||
|
if (simple_string_dictionary_)
|
||||||
|
SetCrashKeyValue(key, value);
|
||||||
|
else
|
||||||
|
upload_parameters_[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashReporterMac::RemoveExtraParameter(const std::string& key) {
|
||||||
|
if (simple_string_dictionary_)
|
||||||
|
simple_string_dictionary_->RemoveKey(key.data());
|
||||||
|
else
|
||||||
|
upload_parameters_.erase(key);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<CrashReporter::UploadReportResult>
|
std::vector<CrashReporter::UploadReportResult>
|
||||||
CrashReporterMac::GetUploadedReports(const base::FilePath& crashes_dir) {
|
CrashReporterMac::GetUploadedReports(const base::FilePath& crashes_dir) {
|
||||||
std::vector<CrashReporter::UploadReportResult> uploaded_reports;
|
std::vector<CrashReporter::UploadReportResult> uploaded_reports;
|
||||||
|
|
|
@ -44,7 +44,7 @@ The `crashReporter` module has the following methods:
|
||||||
Default is `true`.
|
Default is `true`.
|
||||||
* `ignoreSystemCrashHandler` Boolean (optional) - Default is `false`.
|
* `ignoreSystemCrashHandler` Boolean (optional) - Default is `false`.
|
||||||
* `extra` Object (optional) - An object you can define that will be sent along with the
|
* `extra` Object (optional) - An object you can define that will be sent along with the
|
||||||
report. Only string properties are sent correctly, Nested objects are not
|
report. Only string properties are sent correctly. Nested objects are not
|
||||||
supported.
|
supported.
|
||||||
|
|
||||||
You are required to call this method before using any other `crashReporter` APIs
|
You are required to call this method before using any other `crashReporter` APIs
|
||||||
|
@ -60,6 +60,10 @@ reports temporarily. You can test this out by calling `process.crash()` to crash
|
||||||
This will start the process that will monitor and send the crash reports. Replace `submitURL`, `productName`
|
This will start the process that will monitor and send the crash reports. Replace `submitURL`, `productName`
|
||||||
and `crashesDirectory` with appropriate values.
|
and `crashesDirectory` with appropriate values.
|
||||||
|
|
||||||
|
**Note:** If you need send additional/updated `extra` parameters after your
|
||||||
|
first call `start` you can call `setExtraParameter` on macOS or call `start`
|
||||||
|
again with the new/updated `extra` parameters on Linux and Windows.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const args = [
|
const args = [
|
||||||
`--reporter-url=${submitURL}`,
|
`--reporter-url=${submitURL}`,
|
||||||
|
@ -111,6 +115,18 @@ called before `start` is called.
|
||||||
|
|
||||||
**Note:** This API can only be called from the main process.
|
**Note:** This API can only be called from the main process.
|
||||||
|
|
||||||
|
### `crashReporter.setExtraParameter(key, value)` _macOS_
|
||||||
|
|
||||||
|
* `key` String - Parameter key.
|
||||||
|
* `value` String - Parameter value. Specifying `null` or `undefined` will
|
||||||
|
remove the key from the extra parameters.
|
||||||
|
|
||||||
|
Set an extra parameter to set be sent with the crash report. The values
|
||||||
|
specified here will be sent in addition to any values set via the `extra` option
|
||||||
|
when `start` was called. This API is only available on macOS, if you need to
|
||||||
|
add/update extra parameters on Linux and Windows after your first call to
|
||||||
|
`start` you can call `start` again with the updated `extra` options.
|
||||||
|
|
||||||
## Crash Report Payload
|
## Crash Report Payload
|
||||||
|
|
||||||
The crash reporter will send the following data to the `submitURL` as
|
The crash reporter will send the following data to the `submitURL` as
|
||||||
|
|
|
@ -75,7 +75,7 @@ class CrashReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
getUploadedReports () {
|
getUploadedReports () {
|
||||||
return binding._getUploadedReports(this.getCrashesDirectory())
|
return binding.getUploadedReports(this.getCrashesDirectory())
|
||||||
}
|
}
|
||||||
|
|
||||||
getCrashesDirectory () {
|
getCrashesDirectory () {
|
||||||
|
@ -104,7 +104,7 @@ class CrashReporter {
|
||||||
|
|
||||||
getUploadToServer () {
|
getUploadToServer () {
|
||||||
if (process.type === 'browser') {
|
if (process.type === 'browser') {
|
||||||
return binding._getUploadToServer()
|
return binding.getUploadToServer()
|
||||||
} else {
|
} else {
|
||||||
throw new Error('getUploadToServer can only be called from the main process')
|
throw new Error('getUploadToServer can only be called from the main process')
|
||||||
}
|
}
|
||||||
|
@ -112,11 +112,15 @@ class CrashReporter {
|
||||||
|
|
||||||
setUploadToServer (uploadToServer) {
|
setUploadToServer (uploadToServer) {
|
||||||
if (process.type === 'browser') {
|
if (process.type === 'browser') {
|
||||||
return binding._setUploadToServer(uploadToServer)
|
return binding.setUploadToServer(uploadToServer)
|
||||||
} else {
|
} else {
|
||||||
throw new Error('setUploadToServer can only be called from the main process')
|
throw new Error('setUploadToServer can only be called from the main process')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setExtraParameter (key, value) {
|
||||||
|
binding.setExtraParameter(key, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new CrashReporter()
|
module.exports = new CrashReporter()
|
||||||
|
|
|
@ -35,7 +35,7 @@ describe('crashReporter module', function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should send minidump when renderer crashes', function (done) {
|
it('should send minidump when renderer crashes', function (done) {
|
||||||
if (process.platform !== 'darwin') return done()
|
if (process.env.APPVEYOR === 'True') return done()
|
||||||
if (process.env.TRAVIS === 'true') return done()
|
if (process.env.TRAVIS === 'true') return done()
|
||||||
|
|
||||||
this.timeout(120000)
|
this.timeout(120000)
|
||||||
|
@ -55,7 +55,7 @@ describe('crashReporter module', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should send minidump when node processes crash', function (done) {
|
it('should send minidump when node processes crash', function (done) {
|
||||||
if (process.platform !== 'darwin') return done()
|
if (process.env.APPVEYOR === 'True') return done()
|
||||||
if (process.env.TRAVIS === 'true') return done()
|
if (process.env.TRAVIS === 'true') return done()
|
||||||
|
|
||||||
this.timeout(120000)
|
this.timeout(120000)
|
||||||
|
@ -72,6 +72,26 @@ describe('crashReporter module', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should send minidump with updated extra parameters', function (done) {
|
||||||
|
if (process.env.APPVEYOR === 'True') return done()
|
||||||
|
if (process.env.TRAVIS === 'true') return done()
|
||||||
|
|
||||||
|
this.timeout(10000)
|
||||||
|
|
||||||
|
startServer({
|
||||||
|
callback (port) {
|
||||||
|
const crashUrl = url.format({
|
||||||
|
protocol: 'file',
|
||||||
|
pathname: path.join(fixtures, 'api', 'crash-restart.html'),
|
||||||
|
search: '?port=' + port
|
||||||
|
})
|
||||||
|
w.loadURL(crashUrl)
|
||||||
|
},
|
||||||
|
processType: 'renderer',
|
||||||
|
done: done
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('.start(options)', function () {
|
describe('.start(options)', function () {
|
||||||
it('requires that the companyName and submitURL options be specified', function () {
|
it('requires that the companyName and submitURL options be specified', function () {
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
|
@ -111,7 +131,7 @@ describe('crashReporter module', function () {
|
||||||
crashReporter.start({
|
crashReporter.start({
|
||||||
companyName: 'Umbrella Corporation',
|
companyName: 'Umbrella Corporation',
|
||||||
submitURL: 'http://127.0.0.1/crashes',
|
submitURL: 'http://127.0.0.1/crashes',
|
||||||
autoSubmit: true
|
uploadToServer: true
|
||||||
})
|
})
|
||||||
assert.equal(crashReporter.getUploadToServer(), true)
|
assert.equal(crashReporter.getUploadToServer(), true)
|
||||||
crashReporter.setUploadToServer(false)
|
crashReporter.setUploadToServer(false)
|
||||||
|
@ -155,6 +175,7 @@ const startServer = ({callback, processType, done}) => {
|
||||||
assert.equal(fields.platform, process.platform)
|
assert.equal(fields.platform, process.platform)
|
||||||
assert.equal(fields.extra1, 'extra1')
|
assert.equal(fields.extra1, 'extra1')
|
||||||
assert.equal(fields.extra2, 'extra2')
|
assert.equal(fields.extra2, 'extra2')
|
||||||
|
assert.equal(fields.extra3, undefined)
|
||||||
assert.equal(fields._productName, 'Zombies')
|
assert.equal(fields._productName, 'Zombies')
|
||||||
assert.equal(fields._companyName, 'Umbrella Corporation')
|
assert.equal(fields._companyName, 'Umbrella Corporation')
|
||||||
assert.equal(fields._version, app.getVersion())
|
assert.equal(fields._version, app.getVersion())
|
||||||
|
@ -165,6 +186,7 @@ const startServer = ({callback, processType, done}) => {
|
||||||
assert.equal(crashReporter.getLastCrashReport().id, reportId)
|
assert.equal(crashReporter.getLastCrashReport().id, reportId)
|
||||||
assert.notEqual(crashReporter.getUploadedReports().length, 0)
|
assert.notEqual(crashReporter.getUploadedReports().length, 0)
|
||||||
assert.equal(crashReporter.getUploadedReports()[0].id, reportId)
|
assert.equal(crashReporter.getUploadedReports()[0].id, reportId)
|
||||||
|
req.socket.destroy()
|
||||||
done()
|
done()
|
||||||
}, done)
|
}, done)
|
||||||
})
|
})
|
||||||
|
|
46
spec/fixtures/api/crash-restart.html
vendored
Normal file
46
spec/fixtures/api/crash-restart.html
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
|
||||||
|
const {port} = require('url').parse(window.location.href, true).query
|
||||||
|
const {crashReporter} = require('electron')
|
||||||
|
|
||||||
|
crashReporter.start({
|
||||||
|
productName: 'Zombies',
|
||||||
|
companyName: 'Umbrella Corporation',
|
||||||
|
submitURL: 'http://127.0.0.1:' + port,
|
||||||
|
uploadToServer: true,
|
||||||
|
ignoreSystemCrashHandler: true,
|
||||||
|
extra: {
|
||||||
|
extra1: 'extra1',
|
||||||
|
extra2: 'initial',
|
||||||
|
extra3: 'extra3'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
crashReporter.setExtraParameter('extra2', 'extra2')
|
||||||
|
crashReporter.setExtraParameter('extra3', null)
|
||||||
|
} else {
|
||||||
|
crashReporter.start({
|
||||||
|
productName: 'Zombies',
|
||||||
|
companyName: 'Umbrella Corporation',
|
||||||
|
submitURL: 'http://127.0.0.1:' + port,
|
||||||
|
uploadToServer: true,
|
||||||
|
ignoreSystemCrashHandler: true,
|
||||||
|
extra: {
|
||||||
|
extra1: 'extra1',
|
||||||
|
extra2: 'extra2'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
process.crash()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
2
spec/fixtures/api/crash.html
vendored
2
spec/fixtures/api/crash.html
vendored
|
@ -7,7 +7,7 @@ crashReporter.start({
|
||||||
productName: 'Zombies',
|
productName: 'Zombies',
|
||||||
companyName: 'Umbrella Corporation',
|
companyName: 'Umbrella Corporation',
|
||||||
submitURL: 'http://127.0.0.1:' + port,
|
submitURL: 'http://127.0.0.1:' + port,
|
||||||
autoSubmit: true,
|
uploadToServer: true,
|
||||||
ignoreSystemCrashHandler: true,
|
ignoreSystemCrashHandler: true,
|
||||||
extra: {
|
extra: {
|
||||||
'extra1': 'extra1',
|
'extra1': 'extra1',
|
||||||
|
|
Loading…
Reference in a new issue