@logtape/windows-eventlog
Version:
Windows Event Log sink for LogTape
111 lines (109 loc) • 3.69 kB
JavaScript
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
const require_types = require('./types.cjs');
const require_platform = require('./platform.cjs');
const require_ffi_node = require('./ffi.node.cjs');
const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
//#region sink.node.ts
/**
* Formats a log record message into a string suitable for Windows Event Log.
* Combines the template and arguments into a readable message.
*/
function formatMessage(record) {
let message = "";
for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
else {
const arg = record.message[i];
if (typeof arg === "string") message += arg;
else message += JSON.stringify(arg);
}
return message;
}
/**
* Formats additional context information for the log entry.
* Includes category, properties, and other metadata.
*/
function formatContext(record) {
const context = [];
if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
return context.length > 0 ? `\n\n${context.join("\n")}` : "";
}
/**
* Creates a Windows Event Log sink for Node.js environments using FFI.
*
* This implementation uses koffi to call Windows Event Log API directly,
* providing high performance logging without external dependencies.
*
* @param options Configuration options for the sink
* @returns A LogTape sink that writes to Windows Event Log
* @throws {WindowsPlatformError} If not running on Windows
* @throws {WindowsEventLogError} If Event Log operations fail
*
* @example
* ```typescript
* import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
*
* const sink = getWindowsEventLogSink({
* sourceName: "MyApp"
* });
* ```
*
* @since 1.0.0
*/
function getWindowsEventLogSink(options) {
require_platform.validateWindowsPlatform();
const { sourceName, eventIdMapping = {} } = options;
const eventIds = {
...require_types.DEFAULT_EVENT_ID_MAPPING,
...eventIdMapping
};
let ffi = null;
let initPromise = null;
const metaLogger = (0, __logtape_logtape.getLogger)([
"logtape",
"meta",
"windows-eventlog"
]);
const sink = (record) => {
const message = formatMessage(record);
const context = formatContext(record);
const fullMessage = message + context;
const eventType = require_types.mapLogLevelToEventType(record.level);
const eventId = eventIds[record.level];
if (!ffi) {
ffi = new require_ffi_node.WindowsEventLogFFI(sourceName);
initPromise = ffi.initialize().then(() => {
if (ffi) try {
ffi.writeEvent(eventType, eventId, fullMessage);
} catch (error) {
metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
}
}).catch((error) => {
metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
ffi = null;
initPromise = null;
});
} else if (initPromise) initPromise = initPromise.then(() => {
if (ffi) try {
ffi.writeEvent(eventType, eventId, fullMessage);
} catch (error) {
metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
}
});
else try {
ffi.writeEvent(eventType, eventId, fullMessage);
} catch (error) {
metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
}
};
sink[Symbol.dispose] = () => {
if (ffi) {
ffi.dispose();
ffi = null;
}
};
return sink;
}
//#endregion
exports.getWindowsEventLogSink = getWindowsEventLogSink;