UNPKG

@azure/monitor-opentelemetry

Version:
228 lines 9.62 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. Object.defineProperty(exports, "__esModule", { value: true }); exports.DiagFileConsoleLogger = void 0; const tslib_1 = require("tslib"); const node_fs_1 = tslib_1.__importDefault(require("node:fs")); const node_os_1 = tslib_1.__importDefault(require("node:os")); const node_path_1 = tslib_1.__importDefault(require("node:path")); const index_js_1 = require("../../utils/index.js"); class DiagFileConsoleLogger { _TAG = "DiagFileConsoleLogger:"; _cleanupTimeOut = 60 * 30 * 1000; // 30 minutes; _fileCleanupTimer = null; _tempDir; _logFileName; _fileFullPath; _backUpNameFormat; _logToFile = false; _logToConsole = true; _maxHistory; _maxSizeBytes; _logDestination; constructor() { this._logDestination = process.env.APPLICATIONINSIGHTS_LOG_DESTINATION; // destination can be one of file, console or file+console if (this._logDestination === "file+console") { this._logToFile = true; } if (this._logDestination === "file") { this._logToFile = true; this._logToConsole = false; } this._maxSizeBytes = 50000; this._maxHistory = 1; this._logFileName = "applicationinsights.log"; // If custom path not provided use temp folder, /tmp for *nix and USERDIR/AppData/Local/Temp for Windows const logFilePath = process.env.APPLICATIONINSIGHTS_LOGDIR; if (!logFilePath) { this._tempDir = node_path_1.default.join(node_os_1.default.tmpdir(), "appInsights-node"); } else { if (node_path_1.default.isAbsolute(logFilePath)) { this._tempDir = logFilePath; } else { this._tempDir = node_path_1.default.join(process.cwd(), logFilePath); } } this._fileFullPath = node_path_1.default.join(this._tempDir, this._logFileName); this._backUpNameFormat = `.${this._logFileName}`; // {currentime}.applicationinsights.log if (this._logToFile) { if (!this._fileCleanupTimer) { this._fileCleanupTimer = setInterval(() => { // eslint-disable-next-line @typescript-eslint/no-floating-promises this._fileCleanupTask(); }, this._cleanupTimeOut); this._fileCleanupTimer.unref(); } } } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types error(message, ...args) { // Filter out warnings about accessing resource attributes before async attributes are settled if (this._shouldFilterResourceAttributeWarning(message, args)) { return; } // eslint-disable-next-line @typescript-eslint/no-floating-promises this.logMessage(message, args); } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types warn(message, ...args) { // Filter out warnings about accessing resource attributes before async attributes are settled if (this._shouldFilterResourceAttributeWarning(message, args)) { return; } // eslint-disable-next-line @typescript-eslint/no-floating-promises this.logMessage(message, args); } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types info(message, ...args) { // eslint-disable-next-line @typescript-eslint/no-floating-promises this.logMessage(message, args); } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types debug(message, ...args) { // eslint-disable-next-line @typescript-eslint/no-floating-promises this.logMessage(message, args); } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types verbose(message, ...args) { // eslint-disable-next-line @typescript-eslint/no-floating-promises this.logMessage(message, args); } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types async logMessage(message, ...optionalParams) { try { const args = message ? [message, ...optionalParams] : optionalParams; if (this._logToFile) { await this._storeToDisk(args); } if (this._logToConsole) { // eslint-disable-next-line no-console console.log(...args); } } catch (err) { // eslint-disable-next-line no-console console.log(this._TAG, `Failed to log to file: ${err && err.message}`); } } /** * Checks if the warning message should be filtered out to avoid showing * non-actionable warnings to customers */ _shouldFilterResourceAttributeWarning(message, args) { const messagesToFilter = [ "accessing resource attributes before async attributes settled", "resource attributes being accessed before async attributes finished", "async attributes settled", "resource attributes accessed before async detection completed", "module @azure/core-tracing has been loaded before @azure/opentelemetry-instrumentation-azure-sdk", ]; if (typeof message === "string") { if (messagesToFilter.some((filterText) => message.toLowerCase().includes(filterText))) { return true; } } // Check if the message is in the args array if (args && Array.isArray(args)) { for (const arg of args) { if (typeof arg === "string") { if (messagesToFilter.some((filterText) => arg.toLowerCase().includes(filterText))) { return true; } } } } // Also check if message starts with the warning text (in case it's formatted differently) if (typeof message === "string") { const messageParts = message.split(" "); if (messageParts.length >= 3 && messageParts[0].toLowerCase() === "accessing" && messageParts[1].toLowerCase() === "resource" && messageParts[2].toLowerCase() === "attributes") { return true; } } return false; } async _storeToDisk(args) { const data = `${args}\r\n`; try { await (0, index_js_1.confirmDirExists)(this._tempDir); } catch (err) { // eslint-disable-next-line no-console console.log(this._TAG, `Failed to create directory for log file: ${err && err.message}`); return; } try { await (0, index_js_1.accessAsync)(this._fileFullPath, node_fs_1.default.constants.F_OK); } catch (err) { // No file create one try { await (0, index_js_1.appendFileAsync)(this._fileFullPath, data); } catch (appendError) { // eslint-disable-next-line no-console console.log(this._TAG, `Failed to put log into file: ${appendError && appendError.message}`); return; } } // Check size const size = await (0, index_js_1.getShallowFileSize)(this._fileFullPath); if (size && size > this._maxSizeBytes) { await this._createBackupFile(data); } else { await (0, index_js_1.appendFileAsync)(this._fileFullPath, data); } } async _createBackupFile(data) { try { const buffer = await (0, index_js_1.readFileAsync)(this._fileFullPath); const backupPath = node_path_1.default.join(this._tempDir, `${new Date().getTime()}.${this._logFileName}`); await (0, index_js_1.writeFileAsync)(backupPath, buffer); } catch (err) { // eslint-disable-next-line no-console console.log("Failed to generate backup log file", err); } finally { // Store logs await (0, index_js_1.writeFileAsync)(this._fileFullPath, data); } } async _fileCleanupTask() { try { let files = await (0, index_js_1.readdirAsync)(this._tempDir); // Filter only backup files files = files.filter((f) => node_path_1.default.basename(f).indexOf(this._backUpNameFormat) > -1); // Sort by creation date files.sort((a, b) => { // Check expiration const aCreationDate = new Date(parseInt(a.split(this._backUpNameFormat)[0])); const bCreationDate = new Date(parseInt(b.split(this._backUpNameFormat)[0])); if (aCreationDate < bCreationDate) { return -1; } else { return 1; } }); const totalFiles = files.length; for (let i = 0; i < totalFiles - this._maxHistory; i++) { const pathToDelete = node_path_1.default.join(this._tempDir, files[i]); await (0, index_js_1.unlinkAsync)(pathToDelete); } } catch (err) { // eslint-disable-next-line no-console console.log(this._TAG, `Failed to cleanup log files: ${err && err.message}`); } } } exports.DiagFileConsoleLogger = DiagFileConsoleLogger; //# sourceMappingURL=diagFileConsoleLogger.js.map