Skip to content

Commit 45a0871

Browse files
committed
feat: config log file, function name & other improvements
1 parent 886fe46 commit 45a0871

File tree

2 files changed

+95
-29
lines changed

2 files changed

+95
-29
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Each log object contains the following properties:
4545

4646
```ts
4747
import log4js from "log4js";
48-
import jsonLayout from "log4js-json-layout";
48+
import { layout as jsonLayout } from "log4js-json-layout";
4949

5050
log4js.addLayout("json", jsonLayout);
5151
```
@@ -59,6 +59,8 @@ log4js.configure({
5959
type: "stdout",
6060
layout: {
6161
type: "json",
62+
includeFileName: true,
63+
includeFunctionName: true,
6264
},
6365
},
6466
},

index.ts

Lines changed: 92 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,132 @@
1+
import path from "node:path";
2+
import url from "node:url";
13
import util from "node:util";
24
import { isNativeError } from "node:util/types";
35

46
import type log4js from "log4js";
57

68
interface Output {
7-
time: Date; // ISO-8601 format
8-
category: string; // categoy name of log4js instance
9-
level: string; // log4js.Level.levelStr;
10-
msg: string; // data passed to log argument, formated using `util.format`
9+
/**
10+
* ISO-8601 format
11+
*/
12+
time: Date;
13+
/**
14+
* Category name of log4js instance.
15+
*/
16+
category: string;
17+
/**
18+
* log4js.Level.levelStr
19+
*/
20+
level: string;
21+
/**
22+
* Data passed to log argument, formatted using `util.format`.
23+
*/
24+
msg?: string;
25+
/**
26+
* The name of the file where the log message originated
27+
*/
28+
file_name?: string;
29+
/**
30+
* The name of the function where the log message originated
31+
*/
32+
function_name?: string;
33+
}
34+
35+
/**
36+
* Parses the file name from a logging event
37+
*/
38+
function parseFileName(loggingEvent: log4js.LoggingEvent): string | undefined {
39+
let filename = loggingEvent.fileName || "";
40+
if (filename.startsWith("file://")) {
41+
filename = url.fileURLToPath(filename);
42+
}
43+
44+
return filename.split(path.sep).at(-1);
1145
}
1246

13-
function formatter(
14-
event: log4js.LoggingEvent,
15-
config: Config,
16-
): Output {
17-
let output = {
47+
/**
48+
* Formats a log event into the desired output format
49+
*/
50+
function format(event: log4js.LoggingEvent, config?: Config): Output {
51+
const output: Output = {
1852
time: event.startTime,
1953
category: event.categoryName,
2054
level: event.level.levelStr,
21-
msg: "",
22-
} as Output;
55+
};
2356

24-
if (config.withContext) {
57+
if (config?.includeContext) {
2558
Object.assign(output, event.context);
2659
}
2760

28-
let messages: Array<any> | undefined;
61+
if (config?.includeFunctionName && event.functionName) {
62+
output.function_name = event.functionName;
63+
}
64+
65+
if (config?.includeFileName) {
66+
const filename = parseFileName(event);
67+
if (filename) {
68+
output.file_name = filename;
69+
}
70+
}
71+
72+
let msgs: Array<any> | undefined;
2973
if (Array.isArray(event.data)) {
30-
messages = event.data;
74+
msgs = event.data;
3175
} else {
32-
messages = [event.data];
76+
msgs = [event.data];
3377
}
3478

35-
messages = messages
79+
msgs = msgs
3680
.filter((m) => isNativeError(m) || typeof m !== "object")
3781
.filter(Boolean);
3882

39-
output.msg = util.format(...messages);
83+
output.msg = util.format(...msgs);
84+
85+
if (output.msg === undefined) {
86+
delete output.msg;
87+
}
4088

4189
return output;
4290
}
4391

4492
export interface Config {
4593
/**
4694
* Include context added using `log.addContext()`
95+
*
4796
* @default true
4897
*/
49-
withContext?: boolean;
98+
includeContext?: boolean;
99+
/**
100+
* Include function name in json output.
101+
*
102+
* @default false
103+
*/
104+
includeFileName?: boolean;
105+
/**
106+
* Include function name in json output.
107+
*
108+
* @requires log4js>=6.7
109+
* @default false
110+
*/
111+
includeFunctionName?: boolean;
50112
}
51113

52-
const defaults: Config = {
53-
withContext: true,
54-
};
114+
const defaults = {
115+
includeContext: true,
116+
includeFileName: false,
117+
includeFunctionName: false,
118+
} satisfies Config;
55119

56-
export function jsonLayout(config?: Config): log4js.LayoutFunction {
57-
config = Object.assign({}, config, defaults);
120+
/**
121+
* Creates a JSON layout function for log4js.
122+
*/
123+
export function layout(config?: Config): log4js.LayoutFunction {
124+
config = Object.assign({}, defaults, config);
58125

59126
return function layout(event: log4js.LoggingEvent): string {
60-
const formated = formatter(event, config);
61-
127+
const formated = format(event, config);
62128
const output = JSON.stringify(formated);
129+
63130
return output;
64131
};
65132
}
66-
67-
export default jsonLayout;
68-
module.exports = jsonLayout;

0 commit comments

Comments
 (0)