@logtape/windows-eventlog
Version:
Windows Event Log sink for LogTape
115 lines (113 loc) • 3.46 kB
JavaScript
import { DEFAULT_EVENT_ID_MAPPING } from "./types.js";
import { validateWindowsPlatform } from "./platform.js";
import { EVENTLOG_ERROR_TYPE, EVENTLOG_INFORMATION_TYPE, EVENTLOG_WARNING_TYPE, WindowsEventLogFFI } from "./ffi.deno.js";
import { getLogger } from "@logtape/logtape";
//#region sink.deno.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")}` : "";
}
/**
* Maps LogTape log levels to Windows Event Log types.
*/
function getEventType(level) {
switch (level) {
case "fatal":
case "error": return EVENTLOG_ERROR_TYPE;
case "warning": return EVENTLOG_WARNING_TYPE;
case "info":
case "debug":
case "trace":
default: return EVENTLOG_INFORMATION_TYPE;
}
}
/**
* Creates a Windows Event Log sink for Deno environments using FFI.
*
* This implementation uses Deno's Foreign Function Interface to directly
* call Windows Event Log APIs, providing reliable Event Log integration
* without depending on external packages.
*
* @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) {
validateWindowsPlatform();
const { sourceName, eventIdMapping = {} } = options;
const eventIds = {
...DEFAULT_EVENT_ID_MAPPING,
...eventIdMapping
};
let ffi = null;
const metaLogger = getLogger([
"logtape",
"meta",
"windows-eventlog"
]);
const sink = (record) => {
if (!ffi) try {
ffi = new WindowsEventLogFFI(sourceName);
ffi.initialize();
} catch (error) {
metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
return;
}
const message = formatMessage(record);
const context = formatContext(record);
const fullMessage = message + context;
const eventType = getEventType(record.level);
const eventId = eventIds[record.level];
try {
ffi.writeEvent(eventType, eventId, fullMessage);
} catch (error) {
metaLogger.error("Failed to write {level} message to Windows Event Log: {error}", {
level: record.level,
error
});
}
};
sink[Symbol.dispose] = () => {
if (ffi) {
ffi.dispose();
ffi = null;
}
};
return sink;
}
//#endregion
export { getWindowsEventLogSink };
//# sourceMappingURL=sink.deno.js.map