Skip to content

Commit f2ab73b

Browse files
author
Guillaume LE COUSIN
committed
add tests for loggers
1 parent f8387b4 commit f2ab73b

File tree

8 files changed

+307
-128
lines changed

8 files changed

+307
-128
lines changed

net.lecousin.core/src/main/java/net/lecousin/framework/log/LoggerFactory.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
import javax.xml.stream.XMLStreamReader;
1616

1717
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
18-
1918
import net.lecousin.framework.application.Application;
19+
import net.lecousin.framework.concurrent.synch.ISynchronizationPoint;
2020
import net.lecousin.framework.log.Logger.Level;
2121
import net.lecousin.framework.log.appenders.Appender;
2222
import net.lecousin.framework.log.appenders.ConsoleAppender;
@@ -27,7 +27,7 @@ public class LoggerFactory {
2727
Application application;
2828
LoggerThread thread;
2929
private Appender defaultAppender;
30-
private Map<String,Logger> loggers = new HashMap<>(50);
30+
private Map<String, Logger> loggers = new HashMap<>(50);
3131
private Logger defaultLogger;
3232

3333
/** Constructor. */
@@ -76,6 +76,11 @@ public synchronized void setDefault(Appender appender) {
7676
defaultAppender = appender;
7777
}
7878

79+
/** Return a synchronization point that will be unblocked as soon as all pending logs have been written. */
80+
public ISynchronizationPoint<Exception> flush() {
81+
return thread.flush();
82+
}
83+
7984
/** Configure a logger with an appender. */
8085
public synchronized void configure(String name, Appender appender, Level level) {
8186
Logger l = loggers.get(name);

net.lecousin.core/src/main/java/net/lecousin/framework/log/LoggerThread.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ public void run() {
2121
synchronized (logs) {
2222
log = logs.pollFirst();
2323
if (log == null) {
24+
if (flushing != null) {
25+
flushing.unblock();
26+
flushing = null;
27+
}
2428
if (stop) break;
2529
try { logs.wait(); }
2630
catch (InterruptedException e) { break; }
@@ -55,6 +59,7 @@ public ISynchronizationPoint<Exception> closeAsync() {
5559
private Thread thread;
5660
private TurnArray<Pair<Appender,Log>> logs = new TurnArray<>(200);
5761
private boolean stop = false;
62+
private SynchronizationPoint<Exception> flushing = null;
5863

5964
void log(Appender appender, Log log) {
6065
Pair<Appender,Log> p = new Pair<>(appender,log);
@@ -64,4 +69,13 @@ void log(Appender appender, Log log) {
6469
}
6570
}
6671

72+
ISynchronizationPoint<Exception> flush() {
73+
synchronized (logs) {
74+
if (flushing != null) return flushing;
75+
flushing = new SynchronizationPoint<>();
76+
logs.notify();
77+
return flushing;
78+
}
79+
}
80+
6781
}
Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
package net.lecousin.framework.log.appenders;
2-
3-
import net.lecousin.framework.log.LogPattern.Log;
4-
5-
/** Log appender. */
6-
public interface Appender {
7-
8-
/** Append the given log. */
9-
public void append(Log log);
10-
11-
/** Return the level of this appender. */
12-
public int level();
13-
14-
/** Return true if this appender needs the thread name. */
15-
public boolean needsThreadName();
16-
17-
/** Return true if this appender needs the location. */
18-
public boolean needsLocation();
19-
20-
}
1+
package net.lecousin.framework.log.appenders;
2+
3+
import net.lecousin.framework.log.LogPattern.Log;
4+
5+
/** Log appender. */
6+
public interface Appender {
7+
8+
/** Append the given log. */
9+
public void append(Log log);
10+
11+
/** Return the level of this appender. */
12+
public int level();
13+
14+
/** Return true if this appender needs the thread name. */
15+
public boolean needsThreadName();
16+
17+
/** Return true if this appender needs the location. */
18+
public boolean needsLocation();
19+
20+
}
Lines changed: 105 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,105 @@
1-
package net.lecousin.framework.log.appenders;
2-
3-
import java.util.ArrayList;
4-
import java.util.List;
5-
import java.util.Map;
6-
7-
import javax.xml.stream.XMLStreamConstants;
8-
import javax.xml.stream.XMLStreamReader;
9-
10-
import net.lecousin.framework.log.LogPattern.Log;
11-
import net.lecousin.framework.log.Logger.Level;
12-
import net.lecousin.framework.log.LoggerFactory;
13-
14-
/** Log appender that forwards logs to multiple appenders. */
15-
public class MultipleAppender implements Appender {
16-
17-
/** Constructor. */
18-
public MultipleAppender(@SuppressWarnings("unused") LoggerFactory factory, Appender...appenders) {
19-
this.appenders = appenders;
20-
level = Level.OFF.ordinal();
21-
for (Appender a : appenders) {
22-
if (a.level() < level)
23-
level = a.level();
24-
if (!threadName) threadName = a.needsThreadName();
25-
if (!location) location = a.needsLocation();
26-
}
27-
}
28-
29-
/** Constructor. */
30-
public MultipleAppender(
31-
@SuppressWarnings("unused") LoggerFactory factory, XMLStreamReader reader, Map<String,Appender> appenders
32-
) throws Exception {
33-
level = Level.OFF.ordinal();
34-
List<Appender> list = new ArrayList<>();
35-
36-
reader.next();
37-
while (reader.hasNext()) {
38-
if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) {
39-
if ("AppenderRef".equals(reader.getLocalName())) {
40-
String name = null;
41-
for (int i = 0; i < reader.getAttributeCount(); ++i) {
42-
String attrName = reader.getAttributeLocalName(i);
43-
String attrValue = reader.getAttributeValue(i);
44-
if ("name".equals(attrName))
45-
name = attrValue;
46-
else
47-
throw new Exception("Unknown attribute " + attrName + " in AppenderRef");
48-
}
49-
50-
if (name == null) throw new Exception("Missing attribute name on AppenderRef");
51-
Appender appender = appenders.get(name);
52-
if (appender == null) throw new Exception("Unknown appender " + name + " in AppenderRef");
53-
list.add(appender);
54-
if (appender.level() < level)
55-
level = appender.level();
56-
if (!threadName) threadName = appender.needsThreadName();
57-
if (!location) location = appender.needsLocation();
58-
59-
reader.next();
60-
do {
61-
if (reader.getEventType() == XMLStreamConstants.END_ELEMENT)
62-
break;
63-
if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) {
64-
throw new Exception("Unexpected element " + reader.getLocalName() + " in AppenderRef");
65-
}
66-
reader.next();
67-
} while (reader.hasNext());
68-
} else
69-
throw new Exception("Unknown element " + reader.getLocalName()
70-
+ " in MultipleAppender, only AppenderRef elements are expected");
71-
} else if (reader.getEventType() == XMLStreamConstants.END_ELEMENT)
72-
break;
73-
reader.next();
74-
}
75-
76-
this.appenders = list.toArray(new Appender[list.size()]);
77-
}
78-
79-
private Appender[] appenders;
80-
private int level;
81-
private boolean threadName = false;
82-
private boolean location = false;
83-
84-
@Override
85-
public void append(Log log) {
86-
for (Appender a : appenders)
87-
if (a.level() <= log.level.ordinal())
88-
a.append(log);
89-
}
90-
91-
@Override
92-
public int level() {
93-
return level;
94-
}
95-
96-
@Override
97-
public boolean needsThreadName() {
98-
return threadName;
99-
}
100-
101-
@Override
102-
public boolean needsLocation() {
103-
return location;
104-
}
105-
106-
}
1+
package net.lecousin.framework.log.appenders;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
import javax.xml.stream.XMLStreamConstants;
8+
import javax.xml.stream.XMLStreamReader;
9+
10+
import net.lecousin.framework.log.LogPattern.Log;
11+
import net.lecousin.framework.log.Logger.Level;
12+
import net.lecousin.framework.log.LoggerFactory;
13+
14+
/** Log appender that forwards logs to multiple appenders. */
15+
public class MultipleAppender implements Appender {
16+
17+
/** Constructor. */
18+
public MultipleAppender(@SuppressWarnings("unused") LoggerFactory factory, Appender...appenders) {
19+
this.appenders = appenders;
20+
level = Level.OFF.ordinal();
21+
for (Appender a : appenders) {
22+
if (a.level() < level)
23+
level = a.level();
24+
if (!threadName) threadName = a.needsThreadName();
25+
if (!location) location = a.needsLocation();
26+
}
27+
}
28+
29+
/** Constructor. */
30+
public MultipleAppender(
31+
@SuppressWarnings("unused") LoggerFactory factory, XMLStreamReader reader, Map<String,Appender> appenders
32+
) throws Exception {
33+
level = Level.OFF.ordinal();
34+
List<Appender> list = new ArrayList<>();
35+
36+
reader.next();
37+
while (reader.hasNext()) {
38+
if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) {
39+
if ("AppenderRef".equals(reader.getLocalName())) {
40+
String name = null;
41+
for (int i = 0; i < reader.getAttributeCount(); ++i) {
42+
String attrName = reader.getAttributeLocalName(i);
43+
String attrValue = reader.getAttributeValue(i);
44+
if ("name".equals(attrName))
45+
name = attrValue;
46+
else
47+
throw new Exception("Unknown attribute " + attrName + " in AppenderRef");
48+
}
49+
50+
if (name == null) throw new Exception("Missing attribute name on AppenderRef");
51+
Appender appender = appenders.get(name);
52+
if (appender == null) throw new Exception("Unknown appender " + name + " in AppenderRef");
53+
list.add(appender);
54+
if (appender.level() < level)
55+
level = appender.level();
56+
if (!threadName) threadName = appender.needsThreadName();
57+
if (!location) location = appender.needsLocation();
58+
59+
reader.next();
60+
do {
61+
if (reader.getEventType() == XMLStreamConstants.END_ELEMENT)
62+
break;
63+
if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) {
64+
throw new Exception("Unexpected element " + reader.getLocalName() + " in AppenderRef");
65+
}
66+
reader.next();
67+
} while (reader.hasNext());
68+
} else
69+
throw new Exception("Unknown element " + reader.getLocalName()
70+
+ " in MultipleAppender, only AppenderRef elements are expected");
71+
} else if (reader.getEventType() == XMLStreamConstants.END_ELEMENT)
72+
break;
73+
reader.next();
74+
}
75+
76+
this.appenders = list.toArray(new Appender[list.size()]);
77+
}
78+
79+
private Appender[] appenders;
80+
private int level;
81+
private boolean threadName = false;
82+
private boolean location = false;
83+
84+
@Override
85+
public void append(Log log) {
86+
for (Appender a : appenders)
87+
a.append(log);
88+
}
89+
90+
@Override
91+
public int level() {
92+
return level;
93+
}
94+
95+
@Override
96+
public boolean needsThreadName() {
97+
return threadName;
98+
}
99+
100+
@Override
101+
public boolean needsLocation() {
102+
return location;
103+
}
104+
105+
}

net.lecousin.core/src/main/java/net/lecousin/framework/util/StringUtil.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,4 +211,16 @@ public static long parseSize(String s) throws NumberFormatException {
211211
return value * 1024 * 1024 * 1024 * 1024;
212212
throw new NumberFormatException("Invalid size unit: " + s);
213213
}
214+
215+
/** Count the number of occurences. */
216+
public static int count(String string, String toSearch) {
217+
int pos = 0;
218+
int i;
219+
int count = 0;
220+
while ((i = string.indexOf(toSearch, pos)) != -1) {
221+
count++;
222+
pos = i + toSearch.length();
223+
}
224+
return count;
225+
}
214226
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package net.lecousin.framework.core.tests.log;
2+
3+
public class Loggers {
4+
5+
public static class Logger1 {}
6+
7+
public static class Logger2 {}
8+
9+
public static class Logger3 {}
10+
11+
public static class Logger4 {}
12+
13+
public static class Logger5 {}
14+
15+
}

0 commit comments

Comments
 (0)