-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add logic to send analytics data #5545
Merged
ChristopherDedominici
merged 32 commits into
v-next
from
feature/add-logic-to-send-telemetry-data
Aug 20, 2024
+610
−43
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
34a361d
Modify telemetry functions
ChristopherDedominici 24b35bb
add uuid npm package
ChristopherDedominici 4407167
add a method in hh-core to get the telemetry directory
ChristopherDedominici 40b00f5
add main logic (still a few minors TODOs)
ChristopherDedominici a664c3b
add tests
ChristopherDedominici 648592c
small code reorganization
ChristopherDedominici e5d5d4a
Merge branch 'v-next' of github.com:NomicFoundation/hardhat into feat…
ChristopherDedominici 94a3abe
Small PR comments' fixes
ChristopherDedominici c01024a
remove userType. CI is no longer sent
ChristopherDedominici 170f773
remove old analytics client ids
ChristopherDedominici 12a5cd6
Improve naming for functions
ChristopherDedominici 89bbc8a
use builtin method to generate uuid
ChristopherDedominici f1ab5a4
remove unnecessary lambda functions from subprocess'file
ChristopherDedominici 87f6ab4
use taskId and subtaskId instead of taskName and scopeName
ChristopherDedominici b4b96ed
use test keys fro google analytics
ChristopherDedominici 6c7dcf9
remove subtaskId, task is an array of string
ChristopherDedominici 52a7c1a
Merge branch 'v-next' of github.com:NomicFoundation/hardhat into feat…
ChristopherDedominici e3b2c98
Merge branch 'v-next' of github.com:NomicFoundation/hardhat into feat…
ChristopherDedominici 2cb67d4
mark getTelemetryConsent as private and add send user telemetry consent
ChristopherDedominici 12c36c4
small improve in logic and added more tests
ChristopherDedominici a3202f1
add a helper file for telemetry tests
ChristopherDedominici 0fd6555
add ENV variables to simplify testing (e.g.: force to run in non inte…
ChristopherDedominici 141174d
Add test explanation
ChristopherDedominici f1c7c7d
move the check on the ENV variable to force telemetry consent in tests
ChristopherDedominici 3e59fa5
modify helper: wait for subprocess file to be readable
ChristopherDedominici 39a1511
add logic to wait for the file to be readable
ChristopherDedominici b9df707
Smaller fixes based on the PR's comments
ChristopherDedominici 093ae33
Merge branch 'v-next' of github.com:NomicFoundation/hardhat into feat…
ChristopherDedominici 76c4422
add debug module
ChristopherDedominici ab5014b
add logs in telemetry-permission file
ChristopherDedominici e9ecacc
additional debug message
ChristopherDedominici 082b407
Merge branch 'v-next' of github.com:NomicFoundation/hardhat into feat…
ChristopherDedominici File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
v-next/hardhat/src/internal/cli/telemetry/analytics/analytics.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import type { | ||
EventNames, | ||
Payload, | ||
TaskParams, | ||
TelemetryConsentPayload, | ||
} from "./types.js"; | ||
|
||
import os from "node:os"; | ||
|
||
import { spawnDetachedSubProcess } from "@ignored/hardhat-vnext-utils/subprocess"; | ||
import debug from "debug"; | ||
|
||
import { getHardhatVersion } from "../../../utils/package.js"; | ||
import { | ||
isTelemetryAllowedInEnvironment, | ||
isTelemetryAllowed, | ||
} from "../telemetry-permissions.js"; | ||
|
||
import { getAnalyticsClientId } from "./utils.js"; | ||
|
||
const log = debug("hardhat:cli:telemetry:analytics"); | ||
|
||
const SESSION_ID = Math.random().toString(); | ||
const ENGAGEMENT_TIME_MSEC = "10000"; | ||
|
||
// Return a boolean for testing purposes to verify that analytics are not sent in CI environments | ||
export async function sendTelemetryConsentAnalytics( | ||
consent: boolean, | ||
): Promise<boolean> { | ||
// This is a special scenario where only the consent is sent, all the other analytics info | ||
// (like node version, hardhat version, etc.) are stripped. | ||
|
||
if (!isTelemetryAllowedInEnvironment()) { | ||
return false; | ||
} | ||
|
||
const payload: TelemetryConsentPayload = { | ||
client_id: "hardhat_telemetry_consent", | ||
user_id: "hardhat_telemetry_consent", | ||
user_properties: {}, | ||
events: [ | ||
{ | ||
name: "TelemetryConsentResponse", | ||
params: { | ||
userConsent: consent ? "yes" : "no", | ||
}, | ||
}, | ||
], | ||
}; | ||
|
||
await createSubprocessToSendAnalytics(payload); | ||
|
||
return true; | ||
} | ||
|
||
export async function sendTaskAnalytics(taskId: string[]): Promise<boolean> { | ||
const eventParams: TaskParams = { | ||
task: taskId.join(", "), | ||
}; | ||
|
||
return sendAnalytics("task", eventParams); | ||
} | ||
|
||
// Return a boolean for testing purposes to confirm whether analytics were sent based on the consent value and not in CI environments | ||
async function sendAnalytics( | ||
eventName: EventNames, | ||
eventParams: TaskParams, | ||
): Promise<boolean> { | ||
if (!(await isTelemetryAllowed())) { | ||
return false; | ||
} | ||
|
||
const payload = await buildPayload(eventName, eventParams); | ||
|
||
await createSubprocessToSendAnalytics(payload); | ||
|
||
return true; | ||
} | ||
|
||
async function createSubprocessToSendAnalytics( | ||
payload: TelemetryConsentPayload | Payload, | ||
): Promise<void> { | ||
log( | ||
`Sending analytics for '${payload.events[0].name}'. Payload: ${JSON.stringify(payload)}`, | ||
); | ||
|
||
// The HARDHAT_TEST_SUBPROCESS_RESULT_PATH env variable is used in the tests to instruct the subprocess to write the payload to a file | ||
// instead of sending it. | ||
// During testing, the subprocess file is a ts file, whereas in production, it is a js file (compiled code). | ||
// The following lines adjust the file extension based on whether the environment is for testing or production. | ||
const fileExt = | ||
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. Let's document this here with a comment because we'll forget it 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 here, with other smaller fixes |
||
process.env.HARDHAT_TEST_SUBPROCESS_RESULT_PATH !== undefined ? "ts" : "js"; | ||
const subprocessFile = `${import.meta.dirname}/subprocess.${fileExt}`; | ||
|
||
const env: Record<string, string> = {}; | ||
if (process.env.HARDHAT_TEST_SUBPROCESS_RESULT_PATH !== undefined) { | ||
// ATTENTION: only for testing | ||
env.HARDHAT_TEST_SUBPROCESS_RESULT_PATH = | ||
process.env.HARDHAT_TEST_SUBPROCESS_RESULT_PATH; | ||
} | ||
|
||
await spawnDetachedSubProcess(subprocessFile, [JSON.stringify(payload)], env); | ||
|
||
log("Payload sent to detached subprocess"); | ||
} | ||
|
||
async function buildPayload( | ||
eventName: EventNames, | ||
eventParams: TaskParams, | ||
): Promise<Payload> { | ||
const clientId = await getAnalyticsClientId(); | ||
|
||
return { | ||
client_id: clientId, | ||
user_id: clientId, | ||
user_properties: { | ||
projectId: { value: "hardhat-project" }, | ||
hardhatVersion: { value: await getHardhatVersion() }, | ||
operatingSystem: { value: os.platform() }, | ||
nodeVersion: { value: process.version }, | ||
}, | ||
events: [ | ||
{ | ||
name: eventName, | ||
params: { | ||
engagement_time_msec: ENGAGEMENT_TIME_MSEC, | ||
session_id: SESSION_ID, | ||
...eventParams, | ||
}, | ||
}, | ||
], | ||
}; | ||
} |
22 changes: 22 additions & 0 deletions
22
v-next/hardhat/src/internal/cli/telemetry/analytics/subprocess.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { writeJsonFile } from "@ignored/hardhat-vnext-utils/fs"; | ||
import { postJsonRequest } from "@ignored/hardhat-vnext-utils/request"; | ||
|
||
// These keys are expected to be public | ||
// TODO: replace with prod values | ||
const ANALYTICS_URL = "https://www.google-analytics.com/mp/collect"; | ||
const API_SECRET = "iXzTRik5RhahYpgiatSv1w"; | ||
const MEASUREMENT_ID = "G-ZFZWHGZ64H"; | ||
|
||
const payload = JSON.parse(process.argv[2]); | ||
|
||
if (process.env.HARDHAT_TEST_SUBPROCESS_RESULT_PATH === undefined) { | ||
await postJsonRequest(ANALYTICS_URL, payload, { | ||
queryParams: { | ||
api_secret: API_SECRET, | ||
measurement_id: MEASUREMENT_ID, | ||
}, | ||
}); | ||
} else { | ||
// ATTENTION: only for testing | ||
await writeJsonFile(process.env.HARDHAT_TEST_SUBPROCESS_RESULT_PATH, payload); | ||
} |
63 changes: 63 additions & 0 deletions
63
v-next/hardhat/src/internal/cli/telemetry/analytics/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
export interface AnalyticsFile { | ||
analytics: { | ||
clientId: string; | ||
}; | ||
} | ||
|
||
/* eslint-disable @typescript-eslint/naming-convention -- these payload is formatted based on what google analytics expects*/ | ||
export interface BasePayload { | ||
client_id: string; | ||
user_id: string; | ||
user_properties: {}; | ||
events: Array<{ | ||
name: string; | ||
params: { | ||
// From the GA docs: amount of time someone spends with your web | ||
// page in focus or app screen in the foreground. | ||
// The parameter has no use for our app, but it's required in order | ||
// for user activity to display in standard reports like Realtime. | ||
engagement_time_msec?: string; | ||
session_id?: string; | ||
}; | ||
}>; | ||
} | ||
|
||
export interface TelemetryConsentPayload extends BasePayload { | ||
events: Array<{ | ||
name: "TelemetryConsentResponse"; | ||
params: { | ||
userConsent: "yes" | "no"; | ||
session_id?: string; | ||
}; | ||
}>; | ||
} | ||
|
||
export type EventNames = "task"; | ||
|
||
export interface TaskParams { | ||
task: string; | ||
} | ||
|
||
export interface Payload extends BasePayload { | ||
user_properties: { | ||
projectId: { | ||
value: string; | ||
}; | ||
hardhatVersion: { | ||
value: string; | ||
}; | ||
operatingSystem: { | ||
value: string; | ||
}; | ||
nodeVersion: { | ||
value: string; | ||
}; | ||
}; | ||
events: Array<{ | ||
name: EventNames; | ||
params: { | ||
engagement_time_msec: string; | ||
session_id: string; | ||
} & TaskParams; | ||
}>; | ||
} |
58 changes: 58 additions & 0 deletions
58
v-next/hardhat/src/internal/cli/telemetry/analytics/utils.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import type { AnalyticsFile } from "./types.js"; | ||
|
||
import path from "node:path"; | ||
|
||
import { getTelemetryDir } from "@ignored/hardhat-vnext-core/global-dir"; | ||
import { | ||
exists, | ||
readJsonFile, | ||
writeJsonFile, | ||
} from "@ignored/hardhat-vnext-utils/fs"; | ||
import debug from "debug"; | ||
|
||
const log = debug("hardhat:cli:telemetry:analytics:utils"); | ||
|
||
const ANALYTICS_FILE_NAME = "analytics.json"; | ||
|
||
export async function getAnalyticsClientId(): Promise<string> { | ||
let clientId = await readAnalyticsClientId(); | ||
|
||
if (clientId === undefined) { | ||
log("Client Id not found, generating a new one"); | ||
|
||
clientId = crypto.randomUUID(); | ||
await writeAnalyticsClientId(clientId); | ||
} | ||
|
||
return clientId; | ||
} | ||
|
||
async function readAnalyticsClientId(): Promise<string | undefined> { | ||
const globalTelemetryDir = await getTelemetryDir(); | ||
const filePath = path.join(globalTelemetryDir, ANALYTICS_FILE_NAME); | ||
|
||
log(`Looking up Client Id at '${filePath}'`); | ||
|
||
if ((await exists(filePath)) === false) { | ||
return undefined; | ||
} | ||
|
||
const data: AnalyticsFile = await readJsonFile(filePath); | ||
const clientId = data.analytics.clientId; | ||
|
||
log(`Client Id found: ${clientId}`); | ||
|
||
return clientId; | ||
} | ||
|
||
async function writeAnalyticsClientId(clientId: string): Promise<void> { | ||
const globalTelemetryDir = await getTelemetryDir(); | ||
const filePath = path.join(globalTelemetryDir, ANALYTICS_FILE_NAME); | ||
await writeJsonFile(filePath, { | ||
analytics: { | ||
clientId, | ||
}, | ||
}); | ||
|
||
log(`Stored clientId '${clientId}'`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
v-next/hardhat/test/internal/cli/telemetry/analytics/analytics.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import type { Payload } from "../../../../../src/internal/cli/telemetry/analytics/types.js"; | ||
|
||
import assert from "node:assert/strict"; | ||
import path from "node:path"; | ||
import { after, afterEach, before, beforeEach, describe, it } from "node:test"; | ||
|
||
import { readJsonFile, remove } from "@ignored/hardhat-vnext-utils/fs"; | ||
|
||
import { | ||
sendTaskAnalytics, | ||
sendTelemetryConsentAnalytics, | ||
} from "../../../../../src/internal/cli/telemetry/analytics/analytics.js"; | ||
import { getHardhatVersion } from "../../../../../src/internal/utils/package.js"; | ||
import { | ||
checkIfSubprocessWasExecuted, | ||
ROOT_PATH_TO_FIXTURE, | ||
} from "../helpers.js"; | ||
|
||
// | ||
// TEST EXPLANATION: When setting the environment variable HARDHAT_TEST_SUBPROCESS_RESULT_PATH, | ||
// the subprocess writes the payload to the specified file instead of sending it to a remote server. | ||
// This allows us to verify that the payload is formatted correctly. | ||
// | ||
|
||
const PATH_TO_FIXTURE = path.join(ROOT_PATH_TO_FIXTURE, "analytics"); | ||
const RESULT_FILE_PATH = path.join(PATH_TO_FIXTURE, "result.json"); | ||
|
||
describe("analytics", () => { | ||
beforeEach(async () => { | ||
process.env.HARDHAT_TEST_TELEMETRY_CONSENT_VALUE = "true"; | ||
}); | ||
|
||
afterEach(async () => { | ||
delete process.env.HARDHAT_TEST_TELEMETRY_CONSENT_VALUE; | ||
}); | ||
|
||
describe("running in non interactive environment", () => { | ||
it("should not send consent because the environment is non interactive", async () => { | ||
const wasSent = await sendTelemetryConsentAnalytics(true); | ||
assert.equal(wasSent, false); | ||
}); | ||
|
||
it("should not send analytics because the environment is not interactive", async () => { | ||
const wasSent = await sendTaskAnalytics(["task", "subtask"]); | ||
assert.equal(wasSent, false); | ||
}); | ||
}); | ||
|
||
describe("running in an interactive environment (simulated with ENV variables)", () => { | ||
before(() => { | ||
process.env.HARDHAT_TEST_INTERACTIVE_ENV = "true"; | ||
process.env.HARDHAT_TEST_SUBPROCESS_RESULT_PATH = RESULT_FILE_PATH; | ||
}); | ||
|
||
after(() => { | ||
delete process.env.HARDHAT_TEST_INTERACTIVE_ENV; | ||
}); | ||
|
||
beforeEach(async () => { | ||
await remove(RESULT_FILE_PATH); | ||
}); | ||
|
||
afterEach(async () => { | ||
await remove(RESULT_FILE_PATH); | ||
}); | ||
|
||
it("should create the correct payload for the telemetry consent (positive consent)", async () => { | ||
await sendTelemetryConsentAnalytics(true); | ||
|
||
await checkIfSubprocessWasExecuted(RESULT_FILE_PATH, true); | ||
|
||
const result = await readJsonFile(RESULT_FILE_PATH); | ||
|
||
assert.deepEqual(result, { | ||
client_id: "hardhat_telemetry_consent", | ||
user_id: "hardhat_telemetry_consent", | ||
user_properties: {}, | ||
events: [ | ||
{ | ||
name: "TelemetryConsentResponse", | ||
params: { | ||
userConsent: "yes", | ||
}, | ||
}, | ||
], | ||
}); | ||
}); | ||
|
||
it("should create the correct payload for the telemetry consent (negative consent)", async () => { | ||
await sendTelemetryConsentAnalytics(false); | ||
|
||
await checkIfSubprocessWasExecuted(RESULT_FILE_PATH, true); | ||
|
||
const result = await readJsonFile(RESULT_FILE_PATH); | ||
|
||
assert.deepEqual(result, { | ||
client_id: "hardhat_telemetry_consent", | ||
user_id: "hardhat_telemetry_consent", | ||
user_properties: {}, | ||
events: [ | ||
{ | ||
name: "TelemetryConsentResponse", | ||
params: { | ||
userConsent: "no", | ||
}, | ||
}, | ||
], | ||
}); | ||
}); | ||
|
||
it("should create the correct payload for the task analytics", async () => { | ||
const wasSent = await sendTaskAnalytics(["task", "subtask"]); | ||
|
||
await checkIfSubprocessWasExecuted(RESULT_FILE_PATH, true); | ||
|
||
const result: Payload = await readJsonFile(RESULT_FILE_PATH); | ||
|
||
assert.equal(wasSent, true); | ||
|
||
// Check payload properties | ||
assert.notEqual(result.client_id, undefined); | ||
assert.notEqual(result.user_id, undefined); | ||
assert.equal(result.user_properties.projectId.value, "hardhat-project"); | ||
assert.equal( | ||
result.user_properties.hardhatVersion.value, | ||
await getHardhatVersion(), | ||
); | ||
assert.notEqual(result.user_properties.operatingSystem.value, undefined); | ||
assert.notEqual(result.user_properties.nodeVersion.value, undefined); | ||
assert.equal(result.events[0].name, "task"); | ||
assert.equal(result.events[0].params.engagement_time_msec, "10000"); | ||
assert.notEqual(result.events[0].params.session_id, undefined); | ||
assert.equal(result.events[0].params.task, "task, subtask"); | ||
}); | ||
|
||
it("should not send analytics because the consent is not given", async () => { | ||
process.env.HARDHAT_TEST_TELEMETRY_CONSENT_VALUE = "false"; | ||
|
||
const wasSent = await sendTaskAnalytics(["task", "subtask"]); | ||
assert.equal(wasSent, false); | ||
}); | ||
}); | ||
}); |
69 changes: 69 additions & 0 deletions
69
v-next/hardhat/test/internal/cli/telemetry/analytics/utils.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import type { AnalyticsFile } from "../../../../../src/internal/cli/telemetry/analytics/types.js"; | ||
|
||
import assert from "node:assert/strict"; | ||
import path from "node:path"; | ||
import { afterEach, beforeEach, describe, it } from "node:test"; | ||
|
||
import { getTelemetryDir } from "@ignored/hardhat-vnext-core/global-dir"; | ||
import { | ||
readJsonFile, | ||
remove, | ||
writeJsonFile, | ||
} from "@ignored/hardhat-vnext-utils/fs"; | ||
|
||
import { getAnalyticsClientId } from "../../../../../src/internal/cli/telemetry/analytics/utils.js"; | ||
|
||
const CLIENT_ID = "test-client-id"; | ||
|
||
async function createClientIdFile() { | ||
const filePath = await getFilePath(); | ||
await writeJsonFile(filePath, { | ||
analytics: { | ||
clientId: CLIENT_ID, | ||
}, | ||
}); | ||
} | ||
|
||
async function getClientIdFromFile() { | ||
const filePath = await getFilePath(); | ||
const data: AnalyticsFile = await readJsonFile(filePath); | ||
return data.analytics.clientId; | ||
} | ||
|
||
async function deleteClientIdFile() { | ||
const filePath = await getFilePath(); | ||
await remove(filePath); | ||
} | ||
|
||
async function getFilePath() { | ||
return path.join(await getTelemetryDir(), "analytics.json"); | ||
} | ||
|
||
describe("telemetry/analytics/utils", () => { | ||
describe("analyticsClientId", () => { | ||
beforeEach(async () => { | ||
await deleteClientIdFile(); | ||
}); | ||
|
||
afterEach(async () => { | ||
await deleteClientIdFile(); | ||
}); | ||
|
||
it("should generate a new analytics clientId because the clientId is not yet defined", async () => { | ||
const analyticsClientId = await getAnalyticsClientId(); | ||
|
||
// The analyticsClientId should be generate as uuid | ||
assert.notEqual(analyticsClientId, undefined); | ||
assert.notEqual(analyticsClientId, CLIENT_ID); | ||
// The analyticsClientId should also be saved in the file | ||
assert.equal(analyticsClientId, await getClientIdFromFile()); | ||
}); | ||
|
||
it("should get the analyticsClientId from the file because it already exists", async () => { | ||
await createClientIdFile(); | ||
const analyticsClientId = await getClientIdFromFile(); | ||
|
||
assert.equal(analyticsClientId, CLIENT_ID); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import path from "node:path"; | ||
|
||
import { | ||
exists, | ||
readJsonFile, | ||
readUtf8File, | ||
} from "@ignored/hardhat-vnext-utils/fs"; | ||
|
||
export const ROOT_PATH_TO_FIXTURE: string = path.join( | ||
process.cwd(), | ||
"test", | ||
"fixture-projects", | ||
"cli", | ||
"telemetry", | ||
); | ||
|
||
export const TELEMETRY_FOLDER_PATH: string = path.join( | ||
process.cwd(), | ||
"src", | ||
"internal", | ||
"cli", | ||
"telemetry", | ||
); | ||
|
||
export async function checkIfSubprocessWasExecuted( | ||
resultFilePath: string, | ||
isJsonFile: boolean = false, | ||
): Promise<boolean> { | ||
// Checks if the subprocess was executed by waiting for a file to be created. | ||
// Uses an interval to periodically check for the file. If the file isn't found | ||
// within a specified number of attempts, an error is thrown, indicating a failure in subprocess execution. | ||
const MAX_COUNTER = 20; | ||
|
||
return new Promise((resolve, reject) => { | ||
let counter = 0; | ||
|
||
const intervalId = setInterval(async () => { | ||
counter++; | ||
|
||
if (await exists(resultFilePath)) { | ||
try { | ||
// Wait for the file to be readable. The file could exist but the writing could be in progress. | ||
if (isJsonFile) { | ||
await readJsonFile(resultFilePath); | ||
} else { | ||
await readUtf8File(resultFilePath); | ||
} | ||
|
||
clearInterval(intervalId); | ||
resolve(true); | ||
} catch (_err) {} | ||
} else if (counter > MAX_COUNTER) { | ||
clearInterval(intervalId); | ||
reject("Subprocess was not executed in the expected time"); | ||
} | ||
}, 50); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Can we make sure that this dir is not deleted by the
clean --global
task? /cc @schaableThere 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.
I don't think so, as the
global
flag deletes thecache
path and telemetry uses thedata
path.