UNPKG

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
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