diff --git a/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileAccessControl.ts b/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileAccessControl.ts index 98172efa7193..da1997e2ffcf 100644 --- a/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileAccessControl.ts +++ b/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileAccessControl.ts @@ -1,19 +1,20 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as fs from "node:fs"; -import * as os from "node:os"; -import * as child_process from "child_process"; +import { existsSync } from "node:fs"; +import { type as osType } from "node:os"; +import { spawn, spawnSync } from "node:child_process"; import { diag } from "@opentelemetry/api"; +import process from "node:process"; export class FileAccessControl { - private static ICACLS_PATH = `${process.env.systemdrive}/windows/system32/icacls.exe`; - private static POWERSHELL_PATH = `${process.env.systemdrive}/windows/system32/windowspowershell/v1.0/powershell.exe`; + private static ICACLS_PATH = `${process.env.SYSTEMDRIVE}/windows/system32/icacls.exe`; + private static POWERSHELL_PATH = `${process.env.SYSTEMDRIVE}/windows/system32/windowspowershell/v1.0/powershell.exe`; private static ACLED_DIRECTORIES: { [id: string]: boolean } = {}; private static ACL_IDENTITY: string | null = null; private static OS_FILE_PROTECTION_CHECKED = false; public static OS_PROVIDES_FILE_PROTECTION = false; - public static USE_ICACLS = os.type() === "Windows_NT"; + public static USE_ICACLS = osType() === "Windows_NT"; // Check if file access control could be enabled public static checkFileProtection(): void { @@ -29,9 +30,7 @@ export class FileAccessControl { // This should be async - but it's currently safer to have this synchronous // This guarantees we can immediately fail setDiskRetryMode if we need to try { - FileAccessControl.OS_PROVIDES_FILE_PROTECTION = fs.existsSync( - FileAccessControl.ICACLS_PATH, - ); + FileAccessControl.OS_PROVIDES_FILE_PROTECTION = existsSync(FileAccessControl.ICACLS_PATH); } catch (e: any) { // Ignore error } @@ -87,7 +86,7 @@ export class FileAccessControl { private static _runICACLS(args: string[]): Promise { return new Promise((resolve, reject) => { - const aclProc = child_process.spawn(FileAccessControl.ICACLS_PATH, args, { + const aclProc = spawn(FileAccessControl.ICACLS_PATH, args, { windowsHide: true, }); aclProc.on("error", (e: Error) => reject(e)); @@ -105,8 +104,8 @@ export class FileAccessControl { private static _runICACLSSync(args: string[]): void { // Some very old versions of Node (< 0.11) don't have this - if (child_process.spawnSync) { - const aclProc = child_process.spawnSync(FileAccessControl.ICACLS_PATH, args, { + if (spawnSync) { + const aclProc = spawnSync(FileAccessControl.ICACLS_PATH, args, { windowsHide: true, }); if (aclProc.error) { @@ -126,7 +125,7 @@ export class FileAccessControl { if (FileAccessControl.ACL_IDENTITY) { resolve(FileAccessControl.ACL_IDENTITY); } - const psProc = child_process.spawn( + const psProc = spawn( FileAccessControl.POWERSHELL_PATH, ["-Command", "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name"], { @@ -153,8 +152,8 @@ export class FileAccessControl { return FileAccessControl.ACL_IDENTITY; } // Some very old versions of Node (< 0.11) don't have this - if (child_process.spawnSync) { - const psProc = child_process.spawnSync( + if (spawnSync) { + const psProc = spawnSync( FileAccessControl.POWERSHELL_PATH, ["-Command", "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name"], { diff --git a/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileSystemHelpers.ts b/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileSystemHelpers.ts index 07dca56812c5..b53b146a61f0 100644 --- a/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileSystemHelpers.ts +++ b/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileSystemHelpers.ts @@ -2,14 +2,9 @@ // Licensed under the MIT License. import { diag } from "@opentelemetry/api"; -import * as fs from "node:fs"; -import * as path from "node:path"; -import { promisify } from "node:util"; - -const readdirAsync = promisify(fs.readdir); -const statAsync = promisify(fs.stat); -const lstatAsync = promisify(fs.lstat); -const mkdirAsync = promisify(fs.mkdir); +import type { MakeDirectoryOptions } from "node:fs"; +import { join } from "node:path"; +import { lstat, mkdir, readdir, stat } from "node:fs/promises"; /** * Computes the size (in bytes) of all files in a directory at the root level. Asynchronously. @@ -19,11 +14,11 @@ export const getShallowDirectorySize = async (directory: string): Promise => { try { - const stats = await lstatAsync(directory); + const stats = await lstat(directory); if (!stats.isDirectory()) { throw new Error("Path existed but was not a directory"); } } catch (err: any) { if (err && err.code === "ENOENT") { try { - const options: fs.MakeDirectoryOptions = { recursive: true }; - await mkdirAsync(directory, options); + const options: MakeDirectoryOptions = { recursive: true }; + await mkdir(directory, options); } catch (mkdirErr: any) { if (mkdirErr && mkdirErr.code !== "EEXIST") { // Handle race condition by ignoring EEXIST diff --git a/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileSystemPersist.ts b/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileSystemPersist.ts index 3b38aec036f5..fe2ea98bd093 100644 --- a/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileSystemPersist.ts +++ b/sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/persist/fileSystemPersist.ts @@ -1,21 +1,14 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as fs from "node:fs"; -import * as os from "node:os"; -import * as path from "node:path"; +import { tmpdir } from "node:os"; +import { basename, join } from "node:path"; import { diag } from "@opentelemetry/api"; import type { PersistentStorage } from "../../../types.js"; import { FileAccessControl } from "./fileAccessControl.js"; import { confirmDirExists, getShallowDirectorySize } from "./fileSystemHelpers.js"; -import { promisify } from "node:util"; import type { AzureMonitorExporterOptions } from "../../../config.js"; - -const statAsync = promisify(fs.stat); -const readdirAsync = promisify(fs.readdir); -const readFileAsync = promisify(fs.readFile); -const unlinkAsync = promisify(fs.unlink); -const writeFileAsync = promisify(fs.writeFile); +import { readdir, readFile, stat, unlink, writeFile } from "node:fs/promises"; /** * File system persist class. @@ -60,8 +53,8 @@ export class FileSystemPersist implements PersistentStorage { ); } if (this._enabled) { - this._tempDirectory = path.join( - this._options?.storageDirectory || os.tmpdir(), + this._tempDirectory = join( + this._options?.storageDirectory || tmpdir(), "Microsoft", "AzureMonitor", FileSystemPersist.TEMPDIR_PREFIX + this._instrumentationKey, @@ -117,20 +110,20 @@ export class FileSystemPersist implements PersistentStorage { */ private async _getFirstFileOnDisk(): Promise { try { - const stats = await statAsync(this._tempDirectory); + const stats = await stat(this._tempDirectory); if (stats.isDirectory()) { - const origFiles = await readdirAsync(this._tempDirectory); + const origFiles = await readdir(this._tempDirectory); const files = origFiles.filter((f) => - path.basename(f).includes(FileSystemPersist.FILENAME_SUFFIX), + basename(f).includes(FileSystemPersist.FILENAME_SUFFIX), ); if (files.length === 0) { return null; } else { const firstFile = files[0]; - const filePath = path.join(this._tempDirectory, firstFile); - const payload = await readFileAsync(filePath); + const filePath = join(this._tempDirectory, firstFile); + const payload = await readFile(filePath); // delete the file first to prevent double sending - await unlinkAsync(filePath); + await unlink(filePath); return payload; } } @@ -167,12 +160,12 @@ export class FileSystemPersist implements PersistentStorage { } const fileName = `${new Date().getTime()}${FileSystemPersist.FILENAME_SUFFIX}`; - const fileFullPath = path.join(this._tempDirectory, fileName); + const fileFullPath = join(this._tempDirectory, fileName); // Mode 600 is w/r for creator and no read access for others diag.info(`saving data to disk at: ${fileFullPath}`); try { - await writeFileAsync(fileFullPath, payload, { mode: 0o600 }); + await writeFile(fileFullPath, payload, { mode: 0o600 }); } catch (writeError: any) { diag.warn(`Error writing file to persistent file storage`, writeError); return false; @@ -182,11 +175,11 @@ export class FileSystemPersist implements PersistentStorage { private async _fileCleanupTask(): Promise { try { - const stats = await statAsync(this._tempDirectory); + const stats = await stat(this._tempDirectory); if (stats.isDirectory()) { - const origFiles = await readdirAsync(this._tempDirectory); + const origFiles = await readdir(this._tempDirectory); const files = origFiles.filter((f) => - path.basename(f).includes(FileSystemPersist.FILENAME_SUFFIX), + basename(f).includes(FileSystemPersist.FILENAME_SUFFIX), ); if (files.length === 0) { return false; @@ -198,8 +191,8 @@ export class FileSystemPersist implements PersistentStorage { ); const expired = new Date(+new Date() - this.fileRetemptionPeriod) > fileCreationDate; if (expired) { - const filePath = path.join(this._tempDirectory, file); - await unlinkAsync(filePath); + const filePath = join(this._tempDirectory, file); + await unlink(filePath); } }); return true;