@logtape/windows-eventlog 1.4.0-dev.428 → 1.4.0-dev.438
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/ffi.bun.cjs +13 -13
- package/dist/ffi.bun.js +13 -13
- package/dist/ffi.bun.js.map +1 -1
- package/dist/ffi.deno.cjs +21 -20
- package/dist/ffi.deno.js +21 -17
- package/dist/ffi.deno.js.map +1 -1
- package/dist/ffi.node.cjs +10 -15
- package/dist/ffi.node.js +10 -15
- package/dist/ffi.node.js.map +1 -1
- package/dist/formatter.cjs +38 -0
- package/dist/formatter.js +38 -0
- package/dist/formatter.js.map +1 -0
- package/dist/sink.bun.cjs +3 -70
- package/dist/sink.bun.d.cts.map +1 -1
- package/dist/sink.bun.d.ts.map +1 -1
- package/dist/sink.bun.js +4 -70
- package/dist/sink.bun.js.map +1 -1
- package/dist/sink.cjs +84 -0
- package/dist/sink.deno.cjs +3 -84
- package/dist/sink.deno.d.cts.map +1 -1
- package/dist/sink.deno.d.ts.map +1 -1
- package/dist/sink.deno.js +4 -84
- package/dist/sink.deno.js.map +1 -1
- package/dist/sink.js +84 -0
- package/dist/sink.js.map +1 -0
- package/dist/sink.node.cjs +3 -81
- package/dist/sink.node.d.cts.map +1 -1
- package/dist/sink.node.d.ts.map +1 -1
- package/dist/sink.node.js +4 -81
- package/dist/sink.node.js.map +1 -1
- package/dist/types.cjs +16 -7
- package/dist/types.d.cts +6 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +16 -8
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.js","names":["record: LogRecord","context: string[]"],"sources":["../src/formatter.ts"],"sourcesContent":["import type { LogRecord } from \"@logtape/logtape\";\n\n/**\n * Formats a log record message into a string suitable for Windows Event Log.\n * Combines the template and arguments into a readable message.\n */\nfunction formatMessage(record: LogRecord): string {\n let message = \"\";\n\n // Combine template parts with arguments\n for (let i = 0; i < record.message.length; i++) {\n if (i % 2 === 0) {\n // Template part\n message += record.message[i];\n } else {\n // Argument - serialize it\n const arg = record.message[i];\n if (typeof arg === \"string\") {\n message += arg;\n } else {\n message += JSON.stringify(arg);\n }\n }\n }\n\n return message;\n}\n\n/**\n * Formats additional context information for the log entry.\n * Includes category, properties, and other metadata.\n */\nfunction formatContext(record: LogRecord): string {\n const context: string[] = [];\n\n // Add category if present\n if (record.category && record.category.length > 0) {\n context.push(`Category: ${record.category.join(\".\")}`);\n }\n\n // Add properties if present\n if (record.properties && Object.keys(record.properties).length > 0) {\n context.push(`Properties: ${JSON.stringify(record.properties)}`);\n }\n\n // Add timestamp\n context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);\n\n return context.length > 0 ? `\\n\\n${context.join(\"\\n\")}` : \"\";\n}\n\n/**\n * Default way of rendering a record into text that goes in the event log.\n */\nexport function defaultWindowsEventlogFormatter(record: LogRecord): string {\n const msg = formatMessage(record);\n const ctx = formatContext(record);\n return msg + ctx;\n}\n"],"mappings":";;;;;AAMA,SAAS,cAAcA,QAA2B;CAChD,IAAI,UAAU;AAGd,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,IACzC,KAAI,IAAI,MAAM,EAEZ,YAAW,OAAO,QAAQ;MACrB;EAEL,MAAM,MAAM,OAAO,QAAQ;AAC3B,aAAW,QAAQ,SACjB,YAAW;MAEX,YAAW,KAAK,UAAU,IAAI;CAEjC;AAGH,QAAO;AACR;;;;;AAMD,SAAS,cAAcA,QAA2B;CAChD,MAAMC,UAAoB,CAAE;AAG5B,KAAI,OAAO,YAAY,OAAO,SAAS,SAAS,EAC9C,SAAQ,MAAM,YAAY,OAAO,SAAS,KAAK,IAAI,CAAC,EAAE;AAIxD,KAAI,OAAO,cAAc,OAAO,KAAK,OAAO,WAAW,CAAC,SAAS,EAC/D,SAAQ,MAAM,cAAc,KAAK,UAAU,OAAO,WAAW,CAAC,EAAE;AAIlE,SAAQ,MAAM,aAAa,IAAI,KAAK,OAAO,WAAW,aAAa,CAAC,EAAE;AAEtE,QAAO,QAAQ,SAAS,KAAK,MAAM,QAAQ,KAAK,KAAK,CAAC,IAAI;AAC3D;;;;AAKD,SAAgB,gCAAgCD,QAA2B;CACzE,MAAM,MAAM,cAAc,OAAO;CACjC,MAAM,MAAM,cAAc,OAAO;AACjC,QAAO,MAAM;AACd"}
|
package/dist/sink.bun.cjs
CHANGED
|
@@ -1,36 +1,8 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
-
const require_types = require('./types.cjs');
|
|
3
|
-
const require_platform = require('./platform.cjs');
|
|
4
1
|
const require_ffi_bun = require('./ffi.bun.cjs');
|
|
5
|
-
const
|
|
2
|
+
const require_sink = require('./sink.cjs');
|
|
6
3
|
|
|
7
4
|
//#region src/sink.bun.ts
|
|
8
5
|
/**
|
|
9
|
-
* Formats a log record message into a string suitable for Windows Event Log.
|
|
10
|
-
* Combines the template and arguments into a readable message.
|
|
11
|
-
*/
|
|
12
|
-
function formatMessage(record) {
|
|
13
|
-
let message = "";
|
|
14
|
-
for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
|
|
15
|
-
else {
|
|
16
|
-
const arg = record.message[i];
|
|
17
|
-
if (typeof arg === "string") message += arg;
|
|
18
|
-
else message += JSON.stringify(arg);
|
|
19
|
-
}
|
|
20
|
-
return message;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Formats additional context information for the log entry.
|
|
24
|
-
* Includes category, properties, and other metadata.
|
|
25
|
-
*/
|
|
26
|
-
function formatContext(record) {
|
|
27
|
-
const context = [];
|
|
28
|
-
if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
|
|
29
|
-
if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
|
|
30
|
-
context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
|
|
31
|
-
return context.length > 0 ? `\n\n${context.join("\n")}` : "";
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
6
|
* Creates a Windows Event Log sink for Bun environments using FFI.
|
|
35
7
|
*
|
|
36
8
|
* This implementation uses Bun's native Foreign Function Interface to directly
|
|
@@ -54,47 +26,8 @@ function formatContext(record) {
|
|
|
54
26
|
* @since 1.0.0
|
|
55
27
|
*/
|
|
56
28
|
function getWindowsEventLogSink(options) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const eventIds = {
|
|
60
|
-
...require_types.DEFAULT_EVENT_ID_MAPPING,
|
|
61
|
-
...eventIdMapping
|
|
62
|
-
};
|
|
63
|
-
let ffi = null;
|
|
64
|
-
const metaLogger = (0, __logtape_logtape.getLogger)([
|
|
65
|
-
"logtape",
|
|
66
|
-
"meta",
|
|
67
|
-
"windows-eventlog"
|
|
68
|
-
]);
|
|
69
|
-
const sink = (record) => {
|
|
70
|
-
if (!ffi) {
|
|
71
|
-
ffi = new require_ffi_bun.WindowsEventLogFFI(sourceName);
|
|
72
|
-
try {
|
|
73
|
-
ffi.initialize();
|
|
74
|
-
} catch (error) {
|
|
75
|
-
metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
|
|
76
|
-
ffi = null;
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
const message = formatMessage(record);
|
|
81
|
-
const context = formatContext(record);
|
|
82
|
-
const fullMessage = message + context;
|
|
83
|
-
const eventType = require_types.mapLogLevelToEventType(record.level);
|
|
84
|
-
const eventId = eventIds[record.level];
|
|
85
|
-
if (ffi) try {
|
|
86
|
-
ffi.writeEvent(eventType, eventId, fullMessage);
|
|
87
|
-
} catch (error) {
|
|
88
|
-
metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
sink[Symbol.dispose] = () => {
|
|
92
|
-
if (ffi) {
|
|
93
|
-
ffi.dispose();
|
|
94
|
-
ffi = null;
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
return sink;
|
|
29
|
+
const ffi = new require_ffi_bun.WindowsEventLogBunFFI();
|
|
30
|
+
return require_sink.getWindowsEventLogSinkForFFI(ffi, options);
|
|
98
31
|
}
|
|
99
32
|
|
|
100
33
|
//#endregion
|
package/dist/sink.bun.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sink.bun.d.cts","names":[],"sources":["../src/sink.bun.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"sink.bun.d.cts","names":[],"sources":["../src/sink.bun.ts"],"sourcesContent":[],"mappings":";;;;;;;AA4BA;;;;;AAEoB;;;;;;;;;;;;;;;;iBAFJ,sBAAA,UACL,6BACR,OAAO"}
|
package/dist/sink.bun.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sink.bun.d.ts","names":[],"sources":["../src/sink.bun.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"sink.bun.d.ts","names":[],"sources":["../src/sink.bun.ts"],"sourcesContent":[],"mappings":";;;;;;;AA4BA;;;;;AAEoB;;;;;;;;;;;;;;;;iBAFJ,sBAAA,UACL,6BACR,OAAO"}
|
package/dist/sink.bun.js
CHANGED
|
@@ -1,35 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { WindowsEventLogFFI } from "./ffi.bun.js";
|
|
4
|
-
import { getLogger } from "@logtape/logtape";
|
|
1
|
+
import { WindowsEventLogBunFFI } from "./ffi.bun.js";
|
|
2
|
+
import { getWindowsEventLogSinkForFFI } from "./sink.js";
|
|
5
3
|
|
|
6
4
|
//#region src/sink.bun.ts
|
|
7
5
|
/**
|
|
8
|
-
* Formats a log record message into a string suitable for Windows Event Log.
|
|
9
|
-
* Combines the template and arguments into a readable message.
|
|
10
|
-
*/
|
|
11
|
-
function formatMessage(record) {
|
|
12
|
-
let message = "";
|
|
13
|
-
for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
|
|
14
|
-
else {
|
|
15
|
-
const arg = record.message[i];
|
|
16
|
-
if (typeof arg === "string") message += arg;
|
|
17
|
-
else message += JSON.stringify(arg);
|
|
18
|
-
}
|
|
19
|
-
return message;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Formats additional context information for the log entry.
|
|
23
|
-
* Includes category, properties, and other metadata.
|
|
24
|
-
*/
|
|
25
|
-
function formatContext(record) {
|
|
26
|
-
const context = [];
|
|
27
|
-
if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
|
|
28
|
-
if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
|
|
29
|
-
context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
|
|
30
|
-
return context.length > 0 ? `\n\n${context.join("\n")}` : "";
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
6
|
* Creates a Windows Event Log sink for Bun environments using FFI.
|
|
34
7
|
*
|
|
35
8
|
* This implementation uses Bun's native Foreign Function Interface to directly
|
|
@@ -53,47 +26,8 @@ function formatContext(record) {
|
|
|
53
26
|
* @since 1.0.0
|
|
54
27
|
*/
|
|
55
28
|
function getWindowsEventLogSink(options) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const eventIds = {
|
|
59
|
-
...DEFAULT_EVENT_ID_MAPPING,
|
|
60
|
-
...eventIdMapping
|
|
61
|
-
};
|
|
62
|
-
let ffi = null;
|
|
63
|
-
const metaLogger = getLogger([
|
|
64
|
-
"logtape",
|
|
65
|
-
"meta",
|
|
66
|
-
"windows-eventlog"
|
|
67
|
-
]);
|
|
68
|
-
const sink = (record) => {
|
|
69
|
-
if (!ffi) {
|
|
70
|
-
ffi = new WindowsEventLogFFI(sourceName);
|
|
71
|
-
try {
|
|
72
|
-
ffi.initialize();
|
|
73
|
-
} catch (error) {
|
|
74
|
-
metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
|
|
75
|
-
ffi = null;
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
const message = formatMessage(record);
|
|
80
|
-
const context = formatContext(record);
|
|
81
|
-
const fullMessage = message + context;
|
|
82
|
-
const eventType = mapLogLevelToEventType(record.level);
|
|
83
|
-
const eventId = eventIds[record.level];
|
|
84
|
-
if (ffi) try {
|
|
85
|
-
ffi.writeEvent(eventType, eventId, fullMessage);
|
|
86
|
-
} catch (error) {
|
|
87
|
-
metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
sink[Symbol.dispose] = () => {
|
|
91
|
-
if (ffi) {
|
|
92
|
-
ffi.dispose();
|
|
93
|
-
ffi = null;
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
return sink;
|
|
29
|
+
const ffi = new WindowsEventLogBunFFI();
|
|
30
|
+
return getWindowsEventLogSinkForFFI(ffi, options);
|
|
97
31
|
}
|
|
98
32
|
|
|
99
33
|
//#endregion
|
package/dist/sink.bun.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sink.bun.js","names":["
|
|
1
|
+
{"version":3,"file":"sink.bun.js","names":["options: WindowsEventLogSinkOptions"],"sources":["../src/sink.bun.ts"],"sourcesContent":["import type { Sink } from \"@logtape/logtape\";\nimport { WindowsEventLogBunFFI } from \"./ffi.bun.ts\";\nimport { getWindowsEventLogSinkForFFI } from \"./sink.ts\";\nimport type { WindowsEventLogSinkOptions } from \"./types.ts\";\n\n/**\n * Creates a Windows Event Log sink for Bun environments using FFI.\n *\n * This implementation uses Bun's native Foreign Function Interface to directly\n * call Windows Event Log APIs, providing high performance logging optimized\n * for the Bun runtime.\n *\n * @param options Configuration options for the sink\n * @returns A LogTape sink that writes to Windows Event Log\n * @throws {WindowsPlatformError} If not running on Windows\n * @throws {WindowsEventLogError} If Event Log operations fail\n *\n * @example\n * ```typescript\n * import { getWindowsEventLogSink } from \"@logtape/windows-eventlog\";\n *\n * const sink = getWindowsEventLogSink({\n * sourceName: \"MyApp\"\n * });\n * ```\n *\n * @since 1.0.0\n */\nexport function getWindowsEventLogSink(\n options: WindowsEventLogSinkOptions,\n): Sink & Disposable {\n const ffi = new WindowsEventLogBunFFI();\n return getWindowsEventLogSinkForFFI(ffi, options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,uBACdA,SACmB;CACnB,MAAM,MAAM,IAAI;AAChB,QAAO,6BAA6B,KAAK,QAAQ;AAClD"}
|
package/dist/sink.cjs
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_types = require('./types.cjs');
|
|
3
|
+
const require_formatter = require('./formatter.cjs');
|
|
4
|
+
const require_platform = require('./platform.cjs');
|
|
5
|
+
const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
|
|
6
|
+
|
|
7
|
+
//#region src/sink.ts
|
|
8
|
+
/**
|
|
9
|
+
* Helper function to remove any trailing newline that the formatter may add
|
|
10
|
+
* to the string. When writing to the event log, we don't want newlines at the
|
|
11
|
+
* end of the message.
|
|
12
|
+
*/
|
|
13
|
+
function stripTrailingNewline(s) {
|
|
14
|
+
if (s.length > 0 && s.at(s.length - 1) === "\n") return s.substring(0, s.length - 1);
|
|
15
|
+
else return s;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a Windows Event Log sink, parameterized on the FFI implementation.
|
|
19
|
+
*
|
|
20
|
+
* @param {WindowsEventLogFFI} ffi Actual FFI implementation to use
|
|
21
|
+
* @param options Configuration options for the sink
|
|
22
|
+
* @returns A LogTape sink that writes to Windows Event Log
|
|
23
|
+
* @throws {WindowsPlatformError} If not running on Windows
|
|
24
|
+
* @throws {WindowsEventLogError} If Event Log operations fail
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
|
|
29
|
+
*
|
|
30
|
+
* const sink = getWindowsEventLogSink({
|
|
31
|
+
* sourceName: "MyApp"
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @since 1.0.0
|
|
36
|
+
*/
|
|
37
|
+
function getWindowsEventLogSinkForFFI(ffi, options) {
|
|
38
|
+
require_platform.validateWindowsPlatform();
|
|
39
|
+
const { sourceName, eventIdMapping = {} } = options;
|
|
40
|
+
const eventIds = {
|
|
41
|
+
...require_types.DEFAULT_EVENT_ID_MAPPING,
|
|
42
|
+
...eventIdMapping
|
|
43
|
+
};
|
|
44
|
+
const metaLogger = (0, __logtape_logtape.getLogger)([
|
|
45
|
+
"logtape",
|
|
46
|
+
"meta",
|
|
47
|
+
"windows-eventlog"
|
|
48
|
+
]);
|
|
49
|
+
const sink = (record) => {
|
|
50
|
+
try {
|
|
51
|
+
ffi.initialize(sourceName);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const eventType = require_types.mapLogLevelToEventType(record.level);
|
|
57
|
+
const eventId = eventIds[record.level];
|
|
58
|
+
const formatter = options.formatter ?? require_formatter.defaultWindowsEventlogFormatter;
|
|
59
|
+
const fullMessage = stripTrailingNewline(formatter(record));
|
|
60
|
+
const parameters = eventId === require_types.NELOG_OEM_Code ? [
|
|
61
|
+
fullMessage,
|
|
62
|
+
"",
|
|
63
|
+
"",
|
|
64
|
+
"",
|
|
65
|
+
"",
|
|
66
|
+
"",
|
|
67
|
+
"",
|
|
68
|
+
"",
|
|
69
|
+
""
|
|
70
|
+
] : [fullMessage];
|
|
71
|
+
try {
|
|
72
|
+
ffi.writeEvent(eventType, eventId, parameters);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
sink[Symbol.dispose] = () => {
|
|
78
|
+
ffi.dispose();
|
|
79
|
+
};
|
|
80
|
+
return sink;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//#endregion
|
|
84
|
+
exports.getWindowsEventLogSinkForFFI = getWindowsEventLogSinkForFFI;
|
package/dist/sink.deno.cjs
CHANGED
|
@@ -1,50 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
const require_types = require('./types.cjs');
|
|
3
|
-
const require_platform = require('./platform.cjs');
|
|
1
|
+
const require_sink = require('./sink.cjs');
|
|
4
2
|
const require_ffi_deno = require('./ffi.deno.cjs');
|
|
5
|
-
const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
|
|
6
3
|
|
|
7
4
|
//#region src/sink.deno.ts
|
|
8
5
|
/**
|
|
9
|
-
* Formats a log record message into a string suitable for Windows Event Log.
|
|
10
|
-
* Combines the template and arguments into a readable message.
|
|
11
|
-
*/
|
|
12
|
-
function formatMessage(record) {
|
|
13
|
-
let message = "";
|
|
14
|
-
for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
|
|
15
|
-
else {
|
|
16
|
-
const arg = record.message[i];
|
|
17
|
-
if (typeof arg === "string") message += arg;
|
|
18
|
-
else message += JSON.stringify(arg);
|
|
19
|
-
}
|
|
20
|
-
return message;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Formats additional context information for the log entry.
|
|
24
|
-
* Includes category, properties, and other metadata.
|
|
25
|
-
*/
|
|
26
|
-
function formatContext(record) {
|
|
27
|
-
const context = [];
|
|
28
|
-
if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
|
|
29
|
-
if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
|
|
30
|
-
context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
|
|
31
|
-
return context.length > 0 ? `\n\n${context.join("\n")}` : "";
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Maps LogTape log levels to Windows Event Log types.
|
|
35
|
-
*/
|
|
36
|
-
function getEventType(level) {
|
|
37
|
-
switch (level) {
|
|
38
|
-
case "fatal":
|
|
39
|
-
case "error": return require_ffi_deno.EVENTLOG_ERROR_TYPE;
|
|
40
|
-
case "warning": return require_ffi_deno.EVENTLOG_WARNING_TYPE;
|
|
41
|
-
case "info":
|
|
42
|
-
case "debug":
|
|
43
|
-
case "trace":
|
|
44
|
-
default: return require_ffi_deno.EVENTLOG_INFORMATION_TYPE;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
6
|
* Creates a Windows Event Log sink for Deno environments using FFI.
|
|
49
7
|
*
|
|
50
8
|
* This implementation uses Deno's Foreign Function Interface to directly
|
|
@@ -68,47 +26,8 @@ function getEventType(level) {
|
|
|
68
26
|
* @since 1.0.0
|
|
69
27
|
*/
|
|
70
28
|
function getWindowsEventLogSink(options) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const eventIds = {
|
|
74
|
-
...require_types.DEFAULT_EVENT_ID_MAPPING,
|
|
75
|
-
...eventIdMapping
|
|
76
|
-
};
|
|
77
|
-
let ffi = null;
|
|
78
|
-
const metaLogger = (0, __logtape_logtape.getLogger)([
|
|
79
|
-
"logtape",
|
|
80
|
-
"meta",
|
|
81
|
-
"windows-eventlog"
|
|
82
|
-
]);
|
|
83
|
-
const sink = (record) => {
|
|
84
|
-
if (!ffi) try {
|
|
85
|
-
ffi = new require_ffi_deno.WindowsEventLogFFI(sourceName);
|
|
86
|
-
ffi.initialize();
|
|
87
|
-
} catch (error) {
|
|
88
|
-
metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const message = formatMessage(record);
|
|
92
|
-
const context = formatContext(record);
|
|
93
|
-
const fullMessage = message + context;
|
|
94
|
-
const eventType = getEventType(record.level);
|
|
95
|
-
const eventId = eventIds[record.level];
|
|
96
|
-
try {
|
|
97
|
-
ffi.writeEvent(eventType, eventId, fullMessage);
|
|
98
|
-
} catch (error) {
|
|
99
|
-
metaLogger.error("Failed to write {level} message to Windows Event Log: {error}", {
|
|
100
|
-
level: record.level,
|
|
101
|
-
error
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
sink[Symbol.dispose] = () => {
|
|
106
|
-
if (ffi) {
|
|
107
|
-
ffi.dispose();
|
|
108
|
-
ffi = null;
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
return sink;
|
|
29
|
+
const ffi = new require_ffi_deno.WindowsEventLogDenoFFI();
|
|
30
|
+
return require_sink.getWindowsEventLogSinkForFFI(ffi, options);
|
|
112
31
|
}
|
|
113
32
|
|
|
114
33
|
//#endregion
|
package/dist/sink.deno.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sink.deno.d.cts","names":[],"sources":["../src/sink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"sink.deno.d.cts","names":[],"sources":["../src/sink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;AA4BA;;;;;AAEoB;;;;;;;;;;;;;;;;iBAFJ,sBAAA,UACL,6BACR,OAAO"}
|
package/dist/sink.deno.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sink.deno.d.ts","names":[],"sources":["../src/sink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"sink.deno.d.ts","names":[],"sources":["../src/sink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;AA4BA;;;;;AAEoB;;;;;;;;;;;;;;;;iBAFJ,sBAAA,UACL,6BACR,OAAO"}
|
package/dist/sink.deno.js
CHANGED
|
@@ -1,49 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { EVENTLOG_ERROR_TYPE, EVENTLOG_INFORMATION_TYPE, EVENTLOG_WARNING_TYPE, WindowsEventLogFFI } from "./ffi.deno.js";
|
|
4
|
-
import { getLogger } from "@logtape/logtape";
|
|
1
|
+
import { getWindowsEventLogSinkForFFI } from "./sink.js";
|
|
2
|
+
import { WindowsEventLogDenoFFI } from "./ffi.deno.js";
|
|
5
3
|
|
|
6
4
|
//#region src/sink.deno.ts
|
|
7
5
|
/**
|
|
8
|
-
* Formats a log record message into a string suitable for Windows Event Log.
|
|
9
|
-
* Combines the template and arguments into a readable message.
|
|
10
|
-
*/
|
|
11
|
-
function formatMessage(record) {
|
|
12
|
-
let message = "";
|
|
13
|
-
for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
|
|
14
|
-
else {
|
|
15
|
-
const arg = record.message[i];
|
|
16
|
-
if (typeof arg === "string") message += arg;
|
|
17
|
-
else message += JSON.stringify(arg);
|
|
18
|
-
}
|
|
19
|
-
return message;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Formats additional context information for the log entry.
|
|
23
|
-
* Includes category, properties, and other metadata.
|
|
24
|
-
*/
|
|
25
|
-
function formatContext(record) {
|
|
26
|
-
const context = [];
|
|
27
|
-
if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
|
|
28
|
-
if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
|
|
29
|
-
context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
|
|
30
|
-
return context.length > 0 ? `\n\n${context.join("\n")}` : "";
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Maps LogTape log levels to Windows Event Log types.
|
|
34
|
-
*/
|
|
35
|
-
function getEventType(level) {
|
|
36
|
-
switch (level) {
|
|
37
|
-
case "fatal":
|
|
38
|
-
case "error": return EVENTLOG_ERROR_TYPE;
|
|
39
|
-
case "warning": return EVENTLOG_WARNING_TYPE;
|
|
40
|
-
case "info":
|
|
41
|
-
case "debug":
|
|
42
|
-
case "trace":
|
|
43
|
-
default: return EVENTLOG_INFORMATION_TYPE;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
6
|
* Creates a Windows Event Log sink for Deno environments using FFI.
|
|
48
7
|
*
|
|
49
8
|
* This implementation uses Deno's Foreign Function Interface to directly
|
|
@@ -67,47 +26,8 @@ function getEventType(level) {
|
|
|
67
26
|
* @since 1.0.0
|
|
68
27
|
*/
|
|
69
28
|
function getWindowsEventLogSink(options) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const eventIds = {
|
|
73
|
-
...DEFAULT_EVENT_ID_MAPPING,
|
|
74
|
-
...eventIdMapping
|
|
75
|
-
};
|
|
76
|
-
let ffi = null;
|
|
77
|
-
const metaLogger = getLogger([
|
|
78
|
-
"logtape",
|
|
79
|
-
"meta",
|
|
80
|
-
"windows-eventlog"
|
|
81
|
-
]);
|
|
82
|
-
const sink = (record) => {
|
|
83
|
-
if (!ffi) try {
|
|
84
|
-
ffi = new WindowsEventLogFFI(sourceName);
|
|
85
|
-
ffi.initialize();
|
|
86
|
-
} catch (error) {
|
|
87
|
-
metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const message = formatMessage(record);
|
|
91
|
-
const context = formatContext(record);
|
|
92
|
-
const fullMessage = message + context;
|
|
93
|
-
const eventType = getEventType(record.level);
|
|
94
|
-
const eventId = eventIds[record.level];
|
|
95
|
-
try {
|
|
96
|
-
ffi.writeEvent(eventType, eventId, fullMessage);
|
|
97
|
-
} catch (error) {
|
|
98
|
-
metaLogger.error("Failed to write {level} message to Windows Event Log: {error}", {
|
|
99
|
-
level: record.level,
|
|
100
|
-
error
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
sink[Symbol.dispose] = () => {
|
|
105
|
-
if (ffi) {
|
|
106
|
-
ffi.dispose();
|
|
107
|
-
ffi = null;
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
return sink;
|
|
29
|
+
const ffi = new WindowsEventLogDenoFFI();
|
|
30
|
+
return getWindowsEventLogSinkForFFI(ffi, options);
|
|
111
31
|
}
|
|
112
32
|
|
|
113
33
|
//#endregion
|
package/dist/sink.deno.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sink.deno.js","names":["
|
|
1
|
+
{"version":3,"file":"sink.deno.js","names":["options: WindowsEventLogSinkOptions"],"sources":["../src/sink.deno.ts"],"sourcesContent":["import type { Sink } from \"@logtape/logtape\";\nimport { WindowsEventLogDenoFFI } from \"./ffi.deno.ts\";\nimport { getWindowsEventLogSinkForFFI } from \"./sink.ts\";\nimport type { WindowsEventLogSinkOptions } from \"./types.ts\";\n\n/**\n * Creates a Windows Event Log sink for Deno environments using FFI.\n *\n * This implementation uses Deno's Foreign Function Interface to directly\n * call Windows Event Log APIs, providing reliable Event Log integration\n * without depending on external packages.\n *\n * @param options Configuration options for the sink\n * @returns A LogTape sink that writes to Windows Event Log\n * @throws {WindowsPlatformError} If not running on Windows\n * @throws {WindowsEventLogError} If Event Log operations fail\n *\n * @example\n * ```typescript\n * import { getWindowsEventLogSink } from \"@logtape/windows-eventlog\";\n *\n * const sink = getWindowsEventLogSink({\n * sourceName: \"MyApp\"\n * });\n * ```\n *\n * @since 1.0.0\n */\nexport function getWindowsEventLogSink(\n options: WindowsEventLogSinkOptions,\n): Sink & Disposable {\n const ffi = new WindowsEventLogDenoFFI();\n return getWindowsEventLogSinkForFFI(ffi, options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,uBACdA,SACmB;CACnB,MAAM,MAAM,IAAI;AAChB,QAAO,6BAA6B,KAAK,QAAQ;AAClD"}
|
package/dist/sink.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { DEFAULT_EVENT_ID_MAPPING, NELOG_OEM_Code, mapLogLevelToEventType } from "./types.js";
|
|
2
|
+
import { defaultWindowsEventlogFormatter } from "./formatter.js";
|
|
3
|
+
import { validateWindowsPlatform } from "./platform.js";
|
|
4
|
+
import { getLogger } from "@logtape/logtape";
|
|
5
|
+
|
|
6
|
+
//#region src/sink.ts
|
|
7
|
+
/**
|
|
8
|
+
* Helper function to remove any trailing newline that the formatter may add
|
|
9
|
+
* to the string. When writing to the event log, we don't want newlines at the
|
|
10
|
+
* end of the message.
|
|
11
|
+
*/
|
|
12
|
+
function stripTrailingNewline(s) {
|
|
13
|
+
if (s.length > 0 && s.at(s.length - 1) === "\n") return s.substring(0, s.length - 1);
|
|
14
|
+
else return s;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Creates a Windows Event Log sink, parameterized on the FFI implementation.
|
|
18
|
+
*
|
|
19
|
+
* @param {WindowsEventLogFFI} ffi Actual FFI implementation to use
|
|
20
|
+
* @param options Configuration options for the sink
|
|
21
|
+
* @returns A LogTape sink that writes to Windows Event Log
|
|
22
|
+
* @throws {WindowsPlatformError} If not running on Windows
|
|
23
|
+
* @throws {WindowsEventLogError} If Event Log operations fail
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
|
|
28
|
+
*
|
|
29
|
+
* const sink = getWindowsEventLogSink({
|
|
30
|
+
* sourceName: "MyApp"
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @since 1.0.0
|
|
35
|
+
*/
|
|
36
|
+
function getWindowsEventLogSinkForFFI(ffi, options) {
|
|
37
|
+
validateWindowsPlatform();
|
|
38
|
+
const { sourceName, eventIdMapping = {} } = options;
|
|
39
|
+
const eventIds = {
|
|
40
|
+
...DEFAULT_EVENT_ID_MAPPING,
|
|
41
|
+
...eventIdMapping
|
|
42
|
+
};
|
|
43
|
+
const metaLogger = getLogger([
|
|
44
|
+
"logtape",
|
|
45
|
+
"meta",
|
|
46
|
+
"windows-eventlog"
|
|
47
|
+
]);
|
|
48
|
+
const sink = (record) => {
|
|
49
|
+
try {
|
|
50
|
+
ffi.initialize(sourceName);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const eventType = mapLogLevelToEventType(record.level);
|
|
56
|
+
const eventId = eventIds[record.level];
|
|
57
|
+
const formatter = options.formatter ?? defaultWindowsEventlogFormatter;
|
|
58
|
+
const fullMessage = stripTrailingNewline(formatter(record));
|
|
59
|
+
const parameters = eventId === NELOG_OEM_Code ? [
|
|
60
|
+
fullMessage,
|
|
61
|
+
"",
|
|
62
|
+
"",
|
|
63
|
+
"",
|
|
64
|
+
"",
|
|
65
|
+
"",
|
|
66
|
+
"",
|
|
67
|
+
"",
|
|
68
|
+
""
|
|
69
|
+
] : [fullMessage];
|
|
70
|
+
try {
|
|
71
|
+
ffi.writeEvent(eventType, eventId, parameters);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
sink[Symbol.dispose] = () => {
|
|
77
|
+
ffi.dispose();
|
|
78
|
+
};
|
|
79
|
+
return sink;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
export { getWindowsEventLogSinkForFFI };
|
|
84
|
+
//# sourceMappingURL=sink.js.map
|
package/dist/sink.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sink.js","names":["s: string","ffi: WindowsEventLogFFI","options: WindowsEventLogSinkOptions","sink: Sink & Disposable","record: LogRecord"],"sources":["../src/sink.ts"],"sourcesContent":["import type { LogRecord, Sink } from \"@logtape/logtape\";\nimport { getLogger } from \"@logtape/logtape\";\nimport type { WindowsEventLogFFI } from \"./ffi.ts\";\nimport { defaultWindowsEventlogFormatter } from \"./formatter.ts\";\nimport { validateWindowsPlatform } from \"./platform.ts\";\nimport {\n DEFAULT_EVENT_ID_MAPPING,\n mapLogLevelToEventType,\n NELOG_OEM_Code,\n type WindowsEventLogSinkOptions,\n} from \"./types.ts\";\n\n/**\n * Helper function to remove any trailing newline that the formatter may add\n * to the string. When writing to the event log, we don't want newlines at the\n * end of the message.\n */\nfunction stripTrailingNewline(s: string): string {\n if ((s.length > 0) && (s.at(s.length - 1) === \"\\n\")) {\n return s.substring(0, s.length - 1);\n } else {\n return s;\n }\n}\n\n/**\n * Creates a Windows Event Log sink, parameterized on the FFI implementation.\n *\n * @param {WindowsEventLogFFI} ffi Actual FFI implementation to use\n * @param options Configuration options for the sink\n * @returns A LogTape sink that writes to Windows Event Log\n * @throws {WindowsPlatformError} If not running on Windows\n * @throws {WindowsEventLogError} If Event Log operations fail\n *\n * @example\n * ```typescript\n * import { getWindowsEventLogSink } from \"@logtape/windows-eventlog\";\n *\n * const sink = getWindowsEventLogSink({\n * sourceName: \"MyApp\"\n * });\n * ```\n *\n * @since 1.0.0\n */\nexport function getWindowsEventLogSinkForFFI(\n ffi: WindowsEventLogFFI,\n options: WindowsEventLogSinkOptions,\n): Sink & Disposable {\n // Validate platform early\n validateWindowsPlatform();\n\n const {\n sourceName,\n eventIdMapping = {},\n } = options;\n\n // Merge with default event ID mapping\n const eventIds = { ...DEFAULT_EVENT_ID_MAPPING, ...eventIdMapping };\n\n const metaLogger = getLogger([\"logtape\", \"meta\", \"windows-eventlog\"]);\n\n const sink: Sink & Disposable = (record: LogRecord) => {\n try {\n ffi.initialize(sourceName);\n } catch (error) {\n metaLogger.error(\n \"Failed to initialize Windows Event Log FFI: {error}\",\n { error },\n );\n return;\n }\n\n // Get event type and ID for this log level\n const eventType = mapLogLevelToEventType(record.level);\n const eventId = eventIds[record.level];\n\n // Format the complete message using this function\n const formatter = options.formatter ?? defaultWindowsEventlogFormatter;\n const fullMessage = stripTrailingNewline(formatter(record));\n\n // If we are using the generic 3299 event (from netmsg.dll), then we need\n // to pass nine strings as placeholders instead of just one, or the\n // remaining placeholders themselves will be rendered into the text. This\n // assumes that we are not using that particular event ID together with\n // another string resource library.\n const parameters = (eventId === NELOG_OEM_Code)\n ? [fullMessage, \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"]\n : [fullMessage];\n\n // Write to Event Log using FFI\n try {\n ffi.writeEvent(eventType, eventId, parameters);\n } catch (error) {\n metaLogger.error(\n \"Failed to write to Windows Event Log: {error}\",\n { error },\n );\n }\n };\n\n // Implement Disposable for cleanup\n sink[Symbol.dispose] = () => {\n ffi.dispose();\n };\n\n return sink;\n}\n"],"mappings":";;;;;;;;;;;AAiBA,SAAS,qBAAqBA,GAAmB;AAC/C,KAAK,EAAE,SAAS,KAAO,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,KAC5C,QAAO,EAAE,UAAU,GAAG,EAAE,SAAS,EAAE;KAEnC,QAAO;AAEV;;;;;;;;;;;;;;;;;;;;;AAsBD,SAAgB,6BACdC,KACAC,SACmB;AAEnB,0BAAyB;CAEzB,MAAM,EACJ,YACA,iBAAiB,CAAE,GACpB,GAAG;CAGJ,MAAM,WAAW;EAAE,GAAG;EAA0B,GAAG;CAAgB;CAEnE,MAAM,aAAa,UAAU;EAAC;EAAW;EAAQ;CAAmB,EAAC;CAErE,MAAMC,OAA0B,CAACC,WAAsB;AACrD,MAAI;AACF,OAAI,WAAW,WAAW;EAC3B,SAAQ,OAAO;AACd,cAAW,MACT,uDACA,EAAE,MAAO,EACV;AACD;EACD;EAGD,MAAM,YAAY,uBAAuB,OAAO,MAAM;EACtD,MAAM,UAAU,SAAS,OAAO;EAGhC,MAAM,YAAY,QAAQ,aAAa;EACvC,MAAM,cAAc,qBAAqB,UAAU,OAAO,CAAC;EAO3D,MAAM,aAAc,YAAY,iBAC5B;GAAC;GAAa;GAAI;GAAI;GAAI;GAAI;GAAI;GAAI;GAAI;EAAG,IAC7C,CAAC,WAAY;AAGjB,MAAI;AACF,OAAI,WAAW,WAAW,SAAS,WAAW;EAC/C,SAAQ,OAAO;AACd,cAAW,MACT,iDACA,EAAE,MAAO,EACV;EACF;CACF;AAGD,MAAK,OAAO,WAAW,MAAM;AAC3B,MAAI,SAAS;CACd;AAED,QAAO;AACR"}
|