Skip to content
This repository was archived by the owner on Aug 6, 2025. It is now read-only.

Commit ec6b951

Browse files
committed
appender filter
1 parent 4b09059 commit ec6b951

18 files changed

+279
-75
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@ import {configure, LogLevel} from 'log4js2';
4949

5050
configure({
5151
layout : '%d [%p] %c %M:%line:%column - %m %ex',
52-
appenders : [{
53-
appender: 'Console'
54-
}],
52+
appenders : ['Console'],
5553
loggers : [{
5654
tag: 'App',
5755
logLevel : LogLevel.INFO

docs/_includes/sections/appenders.html

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
<h1>Appenders</h1>
22

3-
<h2>Console</h2>
3+
<h2>Configuring</h2>
4+
5+
<p>
6+
By specifying appenders by name, you can control which loggers log to which appender. This is useful when you want
7+
to isolate logs to a specific output file, or prevent certain logs from displaying in the console.
8+
</p>
9+
10+
{% highlight typescript %}
11+
configure({
12+
appenders: ['Console', {
13+
appender: 'File',
14+
fileName: 'app.log'
15+
}, {
16+
name: 'SQLAppender',
17+
appender: 'File',
18+
fileName: 'sql.log'
19+
}],
20+
loggers: [{
21+
tag: 'sql',
22+
appenders: ['SQLAppender'] // will ONLY log to appender named 'SQLAppender'
23+
}]
24+
});
25+
{% endhighlight %}
26+
27+
<h2>Available Appenders</h2>
28+
29+
<h3>Console</h3>
430

531
<p>
632
This is the default appender that outputs logs to the system out. If no appender is specified in the configuration,
@@ -15,7 +41,7 @@ <h2>Console</h2>
1541
});
1642
{% endhighlight %}
1743

18-
<h2>File</h2>
44+
<h3>File</h3>
1945

2046
<p>
2147
This is a simple file appender that outputs logs to a single file. There is no consideration for file size, so it is
@@ -35,7 +61,7 @@ <h2>File</h2>
3561
});
3662
{% endhighlight %}
3763

38-
<h2>Rolling File</h2>
64+
<h3>Rolling File</h3>
3965

4066
<p>
4167
The rolling file appender allows for logs to be appended to a log file, to be split and backed up once the file

docs/_site/index.html

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,31 @@ <h3>Sequence</h3>
439439

440440
<h1>Appenders</h1>
441441

442-
<h2>Console</h2>
442+
<h2>Configuring</h2>
443+
444+
<p>
445+
By specifying appenders by name, you can control which loggers log to which appender. This is useful when you want
446+
to isolate logs to a specific output file, or prevent certain logs from displaying in the console.
447+
</p>
448+
449+
<figure class="highlight"><pre><code class="language-typescript" data-lang="typescript"><span class="nx">configure</span><span class="p">({</span>
450+
<span class="na">appenders</span><span class="p">:</span> <span class="p">[</span><span class="s1">'Console'</span><span class="p">,</span> <span class="p">{</span>
451+
<span class="na">appender</span><span class="p">:</span> <span class="s1">'File'</span><span class="p">,</span>
452+
<span class="na">fileName</span><span class="p">:</span> <span class="s1">'app.log'</span>
453+
<span class="p">},</span> <span class="p">{</span>
454+
<span class="na">name</span><span class="p">:</span> <span class="s1">'SQLAppender'</span><span class="p">,</span>
455+
<span class="na">appender</span><span class="p">:</span> <span class="s1">'File'</span><span class="p">,</span>
456+
<span class="na">fileName</span><span class="p">:</span> <span class="s1">'sql.log'</span>
457+
<span class="p">}],</span>
458+
<span class="na">loggers</span><span class="p">:</span> <span class="p">[{</span>
459+
<span class="na">tag</span><span class="p">:</span> <span class="s1">'sql'</span><span class="p">,</span>
460+
<span class="na">appenders</span><span class="p">:</span> <span class="p">[</span><span class="s1">'SQLAppender'</span><span class="p">]</span> <span class="c1">// will ONLY log to appender named 'SQLAppender'</span>
461+
<span class="p">}]</span>
462+
<span class="p">});</span></code></pre></figure>
463+
464+
<h2>Available Appenders</h2>
465+
466+
<h3>Console</h3>
443467

444468
<p>
445469
This is the default appender that outputs logs to the system out. If no appender is specified in the configuration,
@@ -452,7 +476,7 @@ <h2>Console</h2>
452476
<span class="na">appenders</span><span class="p">:</span> <span class="p">[</span><span class="s1">'Console'</span><span class="p">]</span>
453477
<span class="p">});</span></code></pre></figure>
454478

455-
<h2>File</h2>
479+
<h3>File</h3>
456480

457481
<p>
458482
This is a simple file appender that outputs logs to a single file. There is no consideration for file size, so it is
@@ -470,7 +494,7 @@ <h2>File</h2>
470494
<span class="p">}]</span>
471495
<span class="p">});</span></code></pre></figure>
472496

473-
<h2>Rolling File</h2>
497+
<h3>Rolling File</h3>
474498

475499
<p>
476500
The rolling file appender allows for logs to be appended to a log file, to be split and backed up once the file

src/__mocks__/custom.appender.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ export const CUSTOM_APPENDER_NAME = 'custom';
1717
@Appender(CUSTOM_APPENDER_NAME)
1818
export class CustomAppender extends LogAppender<{}> {
1919

20-
public static get appenderName(): string {
21-
return CUSTOM_APPENDER_NAME;
22-
}
23-
2420
public append(logEvent: ILogEvent) {
2521
if (logEvent.level <= this.getLogLevel()) {
2622
this._append(logEvent);

src/__tests__/logging.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { LogLevel } from '../const/log.level';
2-
import { configure, getLogger } from '../log4js';
2+
import { configure, getLogger } from '../';
33
import { getVirtualConsole } from '../util/virtual.console';
44

55
describe('Message', () => {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { LogFilterAction, Marker } from '../..';
2+
import { AppenderWrapper } from '../appender.wrapper';
3+
import { ConsoleAppender } from '../console.appender';
4+
5+
describe('AppenderWrapper', () => {
6+
7+
test('filter', () => {
8+
9+
const sqlMarker = Marker.getMarker('sql');
10+
const saveMarker = Marker.getMarker('save').setParents(sqlMarker);
11+
const updateMarker = Marker.getMarker('update').setParents(sqlMarker);
12+
13+
const wrapper = new AppenderWrapper(ConsoleAppender, {
14+
appender: ConsoleAppender,
15+
filters: [{
16+
filter: 'Marker',
17+
config: {
18+
onMismatch: LogFilterAction.DENY,
19+
onMatch: LogFilterAction.NEUTRAL,
20+
marker: 'sql'
21+
}
22+
}, {
23+
filter: 'Marker',
24+
config: {
25+
onMismatch: LogFilterAction.NEUTRAL,
26+
onMatch: LogFilterAction.DENY,
27+
marker: 'update'
28+
}
29+
}, {
30+
filter: 'Marker',
31+
config: {
32+
onMismatch: LogFilterAction.NEUTRAL,
33+
onMatch: LogFilterAction.ALLOW,
34+
marker: 'save'
35+
}
36+
}]
37+
});
38+
39+
expect(wrapper.isMatch({
40+
marker: saveMarker,
41+
message: ''
42+
})).toBe(true);
43+
44+
expect(wrapper.isMatch({
45+
marker: updateMarker,
46+
message: ''
47+
})).toBe(false);
48+
49+
expect(wrapper.isMatch({
50+
marker: sqlMarker,
51+
message: ''
52+
})).toBe(true);
53+
54+
});
55+
56+
});

src/appender/__tests__/rolling.file.appender.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,27 @@ import { IRollingFileAppenderConfig } from '../rolling.file.appender';
44

55
describe('RollingFileAppender', () => {
66

7-
beforeAll(() => {
7+
test('test rolling file', async () => {
88

99
configure({
1010
level: LogLevel.DEBUG,
1111
patternLayout: '[%p] %c - %m',
12-
appenders: [{
12+
appenders: ['Console', {
13+
name: 'RollingFile',
1314
appender: RollingFileAppender,
1415
config: {
1516
maxSize: .1,
1617
fileName: './logs/rollingfile.log',
1718
filePattern: './logs/rollingfile.%i.log'
1819
} as IRollingFileAppenderConfig
1920
}],
21+
loggers: [{
22+
tag: 'main',
23+
appenders: ['RollingFile']
24+
}],
2025
virtualConsole: false
2126
});
2227

23-
});
24-
25-
test('test rolling file', async () => {
26-
2728
jest.setTimeout(60000);
2829

2930
function sleep(ms: number) {

src/appender/appender.wrapper.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import IAppenderConfiguration from '../config/appender.config';
2+
import { getFilter } from '../filter';
3+
import { ILogFilterConfiguration, LogFilter } from '../filter/log.filter';
4+
import { LogFilterAction } from '../filter/log.filter.action';
5+
import { ILogEvent } from '../log.event';
6+
import { LogAppender } from './log.appender';
7+
import { Newable } from '../def';
8+
9+
interface IFilterRegister<T extends ILogFilterConfiguration> {
10+
filter: LogFilter<T>;
11+
config: T;
12+
}
13+
14+
export class AppenderWrapper {
15+
16+
private readonly _appender: LogAppender<any>;
17+
private readonly _isPassThrough: boolean;
18+
private readonly _filters: Array<IFilterRegister<any>>;
19+
20+
constructor(appender: Newable<LogAppender<any>>, private readonly _config: IAppenderConfiguration) {
21+
22+
this._appender = new (appender as any)(_config);
23+
24+
this._isPassThrough = (!_config || !_config.filters || _config.filters.length === 0);
25+
if (!this._isPassThrough) {
26+
27+
this._filters = _config.filters.map((filter) => ({
28+
filter: new (getFilter(filter.filter as string) as any)(filter.config),
29+
config: filter.config
30+
}));
31+
32+
} else {
33+
this._filters = [];
34+
}
35+
36+
}
37+
38+
public get appender() {
39+
return this._appender;
40+
}
41+
42+
public append(event: ILogEvent) {
43+
this._appender.append(event);
44+
}
45+
46+
public isMatch(event: ILogEvent): boolean {
47+
48+
return this._isPassThrough || this._isMatch(event);
49+
50+
}
51+
52+
private _isMatch(event: ILogEvent): boolean {
53+
54+
let item: IFilterRegister<any>;
55+
const count = this._filters.length;
56+
for (let i = 0; i < count; i++) {
57+
58+
item = this._filters[i];
59+
if (!item.filter.isMatch(event)) {
60+
if (item.config.onMismatch === LogFilterAction.DENY) {
61+
return false;
62+
} else if (item.config.onMismatch === LogFilterAction.ALLOW) {
63+
return true;
64+
}
65+
} else {
66+
if (item.config.onMatch === LogFilterAction.DENY) {
67+
return false;
68+
} else if (item.config.onMatch === LogFilterAction.ALLOW) {
69+
return true;
70+
}
71+
}
72+
73+
}
74+
75+
return true;
76+
77+
}
78+
79+
}

src/appender/console.appender.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,9 @@ import { ILogEvent } from '../log.event';
44
import { getVirtualConsole } from '../util/virtual.console';
55
import { LogAppender } from './log.appender';
66

7-
@Appender()
7+
@Appender('Console')
88
export class ConsoleAppender extends LogAppender<{}> {
99

10-
/**
11-
* Gets the name of the appender (e.g. 'console')
12-
* @returns {string}
13-
*/
14-
public static get appenderName(): string {
15-
return 'Console';
16-
}
17-
1810
/**
1911
* Appends the log event
2012
* @param {ILogEvent} logEvent

src/appender/file.appender.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,11 @@ export interface IFileAppenderConfig {
77
fileName: string;
88
}
99

10-
@Appender()
10+
@Appender('File')
1111
export class FileAppender extends LogAppender<IFileAppenderConfig> {
1212

1313
private readonly _handler: FileHandler;
1414

15-
/**
16-
* Gets the name of the appender (e.g. 'console')
17-
* @returns {null}
18-
*/
19-
public static get appenderName(): string {
20-
return 'File';
21-
}
22-
2315
constructor(private readonly _config: IFileAppenderConfig) {
2416

2517
super(_config);

0 commit comments

Comments
 (0)