hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
103 lines • 4.43 kB
JavaScript
import { HardhatError, HardhatPluginError, } from "@nomicfoundation/hardhat-errors";
import debug from "debug";
import { ProviderError, UnknownError, } from "../../../builtin-plugins/network-manager/provider-errors.js";
import { getHardhatVersion } from "../../../utils/package.js";
import { isTelemetryAllowed } from "../telemetry-permissions.js";
const log = debug("hardhat:cli:telemetry:sentry:reporter");
// export const SENTRY_DSN =
// "https://d578a176729662a28e7a8da268d36912@o385026.ingest.us.sentry.io/4507685793103872"; // DEV
export const SENTRY_DSN = "https://572b03708e298427cc72fc26dac1e8b2@o385026.ingest.us.sentry.io/4508780138856448"; // PROD
// TODO: This could be done in a more elegant way, but for now, we just
// initialize the entire reporter so that it sets the global error handlers.
export async function setupErrorTelemetryIfEnabled() {
await Reporter.getInstance(true);
}
export async function sendErrorTelemetry(error) {
const instance = await Reporter.getInstance();
return instance.reportErrorViaSubprocess(error);
}
export function setCliHardhatConfigPath(configPath) {
Reporter.setHardhatConfigPath(configPath);
}
// ATTENTION: this function is exported for testing, do not directly use it in production
export function _testResetReporter() {
Reporter.deleteInstance();
}
class Reporter {
// GENERAL EXPLANATION:
// 1) The 'reportError' function collects the error and passes it to our custom Sentry transporter.
// 2) The custom transporter receives the JavaScript error serialized by Sentry.
// 3) This serialized error is then passed to a detached subprocess, which anonymizes all the information before sending it to Sentry.
static #hardhatConfigPath;
static #instance;
#telemetryEnabled;
constructor(telemetryAllowed) {
this.#telemetryEnabled = telemetryAllowed;
}
static setHardhatConfigPath(configPath) {
this.#hardhatConfigPath = configPath;
}
static async getInstance(shouldSetupErrorHandlers = false) {
if (this.#instance !== undefined) {
return this.#instance;
}
const telemetryAllowed = await isTelemetryAllowed();
this.#instance = new Reporter(telemetryAllowed);
if (!telemetryAllowed) {
// No need to initialize Sentry because telemetry is disabled
log("Reporter not initialized because telemetry is not allowed");
return this.#instance;
}
log("Initializing Reporter instance");
const { setExtra } = await import("@sentry/core");
const hardhatVersion = await getHardhatVersion();
const { init } = await import("./init.js");
const { createDetachedProcessTransport } = await import("./transport.js");
const release = `hardhat@${hardhatVersion}`;
const environment = "production";
init({
dsn: SENTRY_DSN,
transport: createDetachedProcessTransport(SENTRY_DSN, release, environment, () => this.#hardhatConfigPath),
release,
environment,
installGlobalHandlers: shouldSetupErrorHandlers,
});
setExtra("nodeVersion", process.version);
setExtra("hardhatVersion", hardhatVersion);
return this.#instance;
}
static deleteInstance() {
// ATTENTION: only for testing
this.#instance = undefined;
}
async reportErrorViaSubprocess(error) {
if (!(await this.#shouldBeReported(error))) {
log("Error not send: this type of error should not be reported");
return false;
}
const { captureException } = await import("@sentry/core");
log("Capturing exception");
captureException(error);
return true;
}
async #shouldBeReported(error) {
if (!this.#telemetryEnabled) {
return false;
}
if (HardhatError.isHardhatError(error) &&
!error.descriptor.shouldBeReported) {
return false;
}
if (HardhatPluginError.isHardhatPluginError(error)) {
// Don't log errors from third-party plugins
return false;
}
if (ProviderError.isProviderError(error) &&
error.code !== UnknownError.CODE) {
// We don't report known network related errors
return false;
}
return true;
}
}
//# sourceMappingURL=reporter.js.map