-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core(lib): add error reporting #2420
Changes from 20 commits
fbd724e
528286d
062fee6
b7f89f6
94f6f54
5ebc608
80f2040
140ac9e
eea3f67
40c0506
2624082
011a77d
14a833a
7ba93f4
37718c2
2891e64
58e186d
7d83585
38c9630
49c061c
cf0e640
637b124
d77270a
6b4f9ea
1aac5a2
a4c982d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Error Reporting Explained | ||
|
||
## What's going on? | ||
|
||
The Lighthouse team is constantly trying to improve the reliability of our tools. We've added functionality to anonymously report runtime exceptions, given your consent, using [Sentry](https://sentry.io/welcome/). We will use this information to detect new bugs and avoid regressions. | ||
|
||
Only CLI users are currently impacted. Node module consumers are opted out by default without a prompt, and the DevTools and extension integrations have no automatic error reporting functionality. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe just include Node module consumers with Devtools and extension users for now since it won't be happening for them? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah was trying to be explicit that the code isn't even there, but that was probably confusing |
||
|
||
## What will happen if I opt-in? | ||
Runtime exceptions will be reported to the team along with information on your environment such as the URL you tested, your OS, and Chrome version. See [what data gets reported](#what-data-gets-reported). | ||
|
||
## What will happen if I opt-out? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
Runtime exceptions will not be reported to the team. Your ability to use Lighthouse will not be affected in any way. | ||
|
||
## What data gets reported? | ||
|
||
* The URL you tested | ||
* The runtime settings used (throttling enabled/disabled, emulation, etc) | ||
* The message, stack trace, and associated data of the error | ||
* Your Lighthouse version | ||
* Your Chrome version | ||
* Your operating system | ||
|
||
## How do I opt-in/opt-out? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe just have "How do I opt-in?" to be clear it's only opt-in? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
The first time you run the CLI you will be prompted with a message asking you if Lighthouse can anonymously report runtime exceptions. You can give a direct response of `yes` or `no` to save your response, and you will not be prompted again. If no response is given within 20 seconds, a `no` response will be assumed, and you will not be prompted again. Non-interactive terminal sessions and invocations with the `CI` environment variable set will automatically be opted out. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "You can give a direct response of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "will automatically be opted out." -> "will automatically not be opted in." maybe? (slightly more awkward but clearer there is no state that needs to be opted out of :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also "y" and "n" work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
The CLI also has two flags to control error reporting that will override the saved preference. Running Lighthouse with `--enable-error-reporting` will report errors regardless of the saved preference, and running Lighthouse with `--no-enable-error-reporting` will *not* report errors regardless of the saved preferences. | ||
|
||
## How do I change my opt-in/opt-out preference? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
Your response to the prompt will be saved to your home directory `~/.config/configstore/lighthouse.json` and used on future runs. To trigger a re-prompt, simply delete this file and Lighthouse will ask again on the next run. You can also edit this json file directly or run Lighthouse with the `--[no-]enable-error-reporting` flags. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ import {GetValidOutputOptions, OutputMode} from './printer'; | |
export interface Flags { | ||
port: number, chromeFlags: string, output: any, outputPath: string, saveArtifacts: boolean, | ||
saveAssets: boolean, view: boolean, maxWaitForLoad: number, logLevel: string, | ||
hostname: string, blockedUrlPatterns: string[] | ||
hostname: string, blockedUrlPatterns: string[], enableErrorReporting: boolean | ||
} | ||
|
||
export function getFlags(manualArgv?: string) { | ||
|
@@ -54,10 +54,12 @@ export function getFlags(manualArgv?: string) { | |
[ | ||
'save-assets', 'save-artifacts', 'list-all-audits', 'list-trace-categories', | ||
'additional-trace-categories', 'config-path', 'chrome-flags', 'perf', 'port', | ||
'hostname', 'max-wait-for-load' | ||
'hostname', 'max-wait-for-load', 'enable-error-reporting' | ||
], | ||
'Configuration:') | ||
.describe({ | ||
'enable-error-reporting': | ||
'Enables error reporting (prompts once by default, setting this flag will force error reporting to that state).', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should add this to the readme. We probably also want to add a note to the readme that the CLI will ask you one time if you want to opt in to sending analytics about errors LH runs into. Opting out will opt out permanently, or you can pass in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
'blocked-url-patterns': 'Block any network requests to the specified URL patterns', | ||
'disable-storage-reset': | ||
'Disable clearing the browser cache and other storage APIs before a run', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -138,13 +138,13 @@ export function saveResults(results: Results, artifacts: Object, flags: Flags) { | |
} | ||
|
||
export async function runLighthouse( | ||
url: string, flags: Flags, config: Object|null): Promise<{}|void> { | ||
url: string, flags: Flags, config: Object|null, environmentData?: Object): Promise<{}|void> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not needed anymore? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
let launchedChrome: LaunchedChrome|undefined; | ||
|
||
try { | ||
launchedChrome = await getDebuggableChrome(flags); | ||
flags.port = launchedChrome.port; | ||
const results = await lighthouse(url, flags, config); | ||
const results = await lighthouse(url, flags, config, environmentData); | ||
|
||
const artifacts = results.artifacts; | ||
delete results.artifacts; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/** | ||
* @license Copyright 2017 Google Inc. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. | ||
*/ | ||
import {Configstore, inquirer} from './shim-modules'; | ||
|
||
const log = require('lighthouse-logger'); | ||
|
||
const MAXIMUM_WAIT_TIME = 20 * 1000; | ||
// clang-format off | ||
const MESSAGE = | ||
`${log.reset}We're constantly trying to improve Lighthouse and its reliability.\n ` + | ||
`May we anonymously report runtime exceptions to improve the tool over time?\n ` + | ||
`${log.reset}Learn more: https://github.com/GoogleChrome/lighthouse/blob/master/docs/error-reporting.md`; | ||
// clang-format on | ||
|
||
async function prompt() { | ||
if (!process.stdout.isTTY || process.env.CI) { | ||
// Default non-interactive sessions to false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wdyt about defaulting CI to true? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm I'm definitely against in our CI so an opt-out env variable seems good. It'd be nice to gather errors from folks running Lighthouse in CI, but silently opting them in seems bad. Can always use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do like the idea of enabling this for our smoke tests on master though 👍 followup work There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok sg |
||
return false; | ||
} | ||
|
||
let timeout: NodeJS.Timer; | ||
|
||
const prompt = inquirer.prompt([ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm strange, I can't repro, it happens every time? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
type: 'confirm', | ||
name: 'isErrorReportingEnabled', | ||
default: false, | ||
message: MESSAGE, | ||
}, | ||
]); | ||
|
||
const timeoutPromise = new Promise((resolve: (a: boolean) => {}) => { | ||
timeout = setTimeout(() => { | ||
prompt.ui.close(); | ||
process.stdout.write('\n'); | ||
log.warn('CLI', 'No response to error logging preference, errors will not be reported.'); | ||
resolve(false); | ||
}, MAXIMUM_WAIT_TIME); | ||
}); | ||
|
||
return Promise.race([ | ||
prompt.then((result: {isErrorReportingEnabled: boolean}) => { | ||
clearTimeout(timeout); | ||
return result.isErrorReportingEnabled; | ||
}), | ||
timeoutPromise, | ||
]); | ||
} | ||
|
||
export async function askPermission() { | ||
const configstore = new Configstore('lighthouse'); | ||
let isErrorReportingEnabled = configstore.get('isErrorReportingEnabled'); | ||
if (typeof isErrorReportingEnabled === 'boolean') { | ||
return isErrorReportingEnabled; | ||
} | ||
|
||
isErrorReportingEnabled = await prompt(); | ||
configstore.set('isErrorReportingEnabled', isErrorReportingEnabled); | ||
return isErrorReportingEnabled; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ describe('CLI run', function() { | |
const url = 'chrome://version'; | ||
const filename = path.join(process.cwd(), 'run.ts.results.json'); | ||
const flags = getFlags(`--output=json --output-path=${filename} ${url}`); | ||
flags.enableErrorReporting = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why use this here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. otherwise the mock and expected errors from tests get reported to sentry, this test skips bin.ts where we do the prompting/setting to false for CI |
||
return run.runLighthouse(url, flags, fastConfig).then(passedResults => { | ||
assert.ok(fs.existsSync(filename)); | ||
const results = JSON.parse(fs.readFileSync(filename, 'utf-8')); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
const Audit = require('./audit'); | ||
const URL = require('../lib/url-shim'); | ||
const Emulation = require('../lib/emulation'); | ||
const Sentry = require('../lib/sentry'); | ||
const Util = require('../report/v2/renderer/util.js'); | ||
|
||
// Maximum TTFI to be considered "fast" for PWA baseline checklist | ||
|
@@ -111,6 +112,22 @@ class LoadFastEnough4Pwa extends Audit { | |
} | ||
|
||
if (!areLatenciesAll3G) { | ||
const sentryContext = Sentry.getContext(); | ||
const hadThrottlingEnabled = sentryContext && sentryContext.extra && | ||
sentryContext.extra.networkThrottling; | ||
|
||
if (hadThrottlingEnabled) { | ||
// Track these instances in Sentry since there should be no requests that are fast when | ||
// throttling is enabled, and it's likely a throttling bug we should look into. | ||
const violatingLatency = firstRequestLatencies | ||
.find(item => Number(item.latency) < latency3gMin); | ||
Sentry.captureMessage('Network request latencies were not realistic', { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would you mind adding a comment to each of these special sentry captures why they're worth capturing (vs not or letting the error handler get them) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah |
||
tags: {audit: this.meta.name}, | ||
extra: {violatingLatency}, | ||
level: 'warning', | ||
}); | ||
} | ||
|
||
return { | ||
rawValue: true, | ||
// eslint-disable-next-line max-len | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe
"If you give your consent, we've added functionality to anonymously report runtime exceptions using [Sentry](https://sentry.io/welcome/)."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
heh, but the functionality is there if they give consent or not, the phrase is modifying "report" ;)
rephrased