Skip to content

Commit be9e210

Browse files
committed
Add new java platform logger
1 parent d728ec4 commit be9e210

File tree

10 files changed

+369
-2
lines changed

10 files changed

+369
-2
lines changed

driver/clirr-ignored-differences.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,4 +409,10 @@
409409
<method>org.neo4j.driver.BaseSession session(java.lang.Class, org.neo4j.driver.SessionConfig)</method>
410410
</difference>
411411

412+
<difference>
413+
<className>org/neo4j/driver/Logging</className>
414+
<differenceType>7012</differenceType>
415+
<method>org.neo4j.driver.Logging javaPlatformLogging()</method>
416+
</difference>
417+
412418
</differences>

driver/src/main/java/module-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
requires io.netty.buffer;
3636
requires io.netty.codec;
3737
requires io.netty.resolver;
38-
requires transitive java.logging;
38+
requires static java.logging;
3939
requires transitive org.reactivestreams;
4040
requires static micrometer.core;
4141
requires static org.graalvm.nativeimage.builder;

driver/src/main/java/org/neo4j/driver/Logging.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.logging.Level;
2525
import org.neo4j.driver.internal.logging.ConsoleLogging;
2626
import org.neo4j.driver.internal.logging.JULogging;
27+
import org.neo4j.driver.internal.logging.JavaPlatformLogging;
2728
import org.neo4j.driver.internal.logging.Slf4jLogging;
2829

2930
/**
@@ -33,6 +34,9 @@
3334
* <li>{@link #slf4j() SLF4J logging} - uses available SLF4J binding (Logback, Log4j, etc.) fails when no SLF4J implementation is available. Uses
3435
* application's logging configuration from XML or other type of configuration file. This logging method is the preferred one and relies on the SLF4J
3536
* implementation available in the classpath or modulepath.</li>
37+
* <li>{@link #javaPlatformLogging() Java Logging API} - uses {@link java.lang.System.Logger} created via
38+
* {@link java.lang.System#getLogger(String)}. This logging method is suitable when application
39+
* uses the java system logger api for logging and provides the appropriate implementation (Logback, Log4j, etc.)</li>
3640
* <li>{@link #javaUtilLogging(Level) Java Logging API (JUL)} - uses {@link java.util.logging.Logger} created via
3741
* {@link java.util.logging.Logger#getLogger(String)}. Global java util logging configuration applies. This logging method is suitable when application
3842
* uses JUL for logging and explicitly configures it.</li>
@@ -118,13 +122,27 @@ static Logging slf4j() {
118122
return new Slf4jLogging();
119123
}
120124

125+
/**
126+
* Create logging implementation that uses {@link java.lang.System.Logger}.
127+
*
128+
* @return new logging implementation.
129+
*/
130+
static Logging javaPlatformLogging() {
131+
return new JavaPlatformLogging();
132+
}
133+
121134
/**
122135
* Create logging implementation that uses {@link java.util.logging}.
123136
*
124137
* @param level the log level.
125138
* @return new logging implementation.
139+
* @throws IllegalStateException if java.logging is not available.
126140
*/
127141
static Logging javaUtilLogging(Level level) {
142+
IllegalStateException unavailabilityError = JULogging.checkAvailability();
143+
if (unavailabilityError != null) {
144+
throw unavailabilityError;
145+
}
128146
return new JULogging(level);
129147
}
130148

driver/src/main/java/org/neo4j/driver/internal/logging/JULogging.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,15 @@ public JULogging(Level loggingLevel) {
4242
public Logger getLog(String name) {
4343
return new JULogger(name, loggingLevel);
4444
}
45+
46+
public static IllegalStateException checkAvailability() {
47+
try {
48+
Class.forName("java.util.logging.Logger");
49+
return null;
50+
} catch (Throwable error) {
51+
return new IllegalStateException(
52+
"java.util.logging is not available. Please add the java.logging module.",
53+
error);
54+
}
55+
}
4556
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.internal.logging;
20+
21+
import org.neo4j.driver.Logger;
22+
23+
import java.lang.System.Logger.Level;
24+
import java.util.Objects;
25+
26+
public class JavaPlatformLogger implements Logger {
27+
private final java.lang.System.Logger delegate;
28+
29+
public JavaPlatformLogger(System.Logger delegate) {
30+
this.delegate = Objects.requireNonNull(delegate);
31+
}
32+
33+
@Override
34+
public void error(String message, Throwable cause) {
35+
if (delegate.isLoggable(Level.ERROR)) {
36+
delegate.log(Level.ERROR, message, cause);
37+
}
38+
}
39+
40+
@Override
41+
public void info(String format, Object... params) {
42+
if (delegate.isLoggable(Level.INFO)) {
43+
delegate.log(Level.INFO, String.format(format, params));
44+
}
45+
}
46+
47+
@Override
48+
public void warn(String format, Object... params) {
49+
if (delegate.isLoggable(Level.WARNING)) {
50+
delegate.log(Level.WARNING, String.format(format, params));
51+
}
52+
}
53+
54+
@Override
55+
public void warn(String message, Throwable cause) {
56+
if (delegate.isLoggable(Level.WARNING)) {
57+
delegate.log(Level.WARNING, message, cause);
58+
}
59+
}
60+
61+
@Override
62+
public void debug(String format, Object... params) {
63+
if (isDebugEnabled()) {
64+
delegate.log(Level.DEBUG, String.format(format, params));
65+
}
66+
}
67+
68+
@Override
69+
public void debug(String message, Throwable throwable) {
70+
if (isDebugEnabled()) {
71+
delegate.log(Level.DEBUG, message, throwable);
72+
}
73+
}
74+
75+
@Override
76+
public void trace(String format, Object... params) {
77+
if (isTraceEnabled()) {
78+
delegate.log(Level.TRACE, String.format(format, params));
79+
}
80+
}
81+
82+
@Override
83+
public boolean isTraceEnabled() {
84+
return delegate.isLoggable(Level.TRACE);
85+
}
86+
87+
@Override
88+
public boolean isDebugEnabled() {
89+
return delegate.isLoggable(Level.DEBUG);
90+
}
91+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.internal.logging;
20+
21+
import org.neo4j.driver.Logger;
22+
import org.neo4j.driver.Logging;
23+
24+
import java.io.Serializable;
25+
26+
/**
27+
* Internal implementation of the java platform logging module.
28+
* <b>This class should not be used directly.</b> Please use {@link Logging#javaPlatformLogging()} factory method instead.
29+
*
30+
* @see Logging#javaPlatformLogging()
31+
*/
32+
public class JavaPlatformLogging implements Logging, Serializable {
33+
private static final long serialVersionUID = -1145576859241657833L;
34+
35+
public JavaPlatformLogging() {
36+
}
37+
38+
@Override
39+
public Logger getLog(String name) {
40+
return new JavaPlatformLogger(System.getLogger(name));
41+
}
42+
}

driver/src/test/java/org/neo4j/driver/ConfigTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.neo4j.driver.internal.logging.DevNullLogging;
4848
import org.neo4j.driver.internal.logging.JULogging;
4949
import org.neo4j.driver.internal.logging.Slf4jLogging;
50+
import org.neo4j.driver.internal.logging.JavaPlatformLogging;
5051
import org.neo4j.driver.net.ServerAddressResolver;
5152
import org.neo4j.driver.testutil.TestUtil;
5253

@@ -486,7 +487,7 @@ void shouldSerializeSerializableLogging() throws IOException, ClassNotFoundExcep
486487
}
487488

488489
@ParameterizedTest
489-
@ValueSource(classes = {DevNullLogging.class, JULogging.class, ConsoleLogging.class, Slf4jLogging.class})
490+
@ValueSource(classes = {DevNullLogging.class, JULogging.class, ConsoleLogging.class, Slf4jLogging.class, JavaPlatformLogging.class})
490491
void officialLoggingProvidersShouldBeSerializable(Class<? extends Logging> loggingClass) {
491492
assertTrue(Serializable.class.isAssignableFrom(loggingClass));
492493
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.internal.logging;
20+
21+
import org.junit.jupiter.api.Test;
22+
import org.neo4j.driver.Logger;
23+
24+
import java.util.logging.Level;
25+
26+
import static org.hamcrest.Matchers.instanceOf;
27+
import static org.hamcrest.junit.MatcherAssert.assertThat;
28+
import static org.junit.jupiter.api.Assertions.assertNull;
29+
30+
class JULoggingTest {
31+
@Test
32+
void shouldCreateLoggers() {
33+
JULogging logging = new JULogging(Level.ALL);
34+
35+
Logger logger = logging.getLog("My Log");
36+
37+
assertThat(logger, instanceOf(JULogger.class));
38+
}
39+
40+
@Test
41+
void shouldCheckIfAvailable() {
42+
assertNull(JULogging.checkAvailability());
43+
}
44+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.internal.logging;
20+
21+
import org.junit.jupiter.api.Test;
22+
import org.mockito.Mockito;
23+
24+
import static org.junit.jupiter.api.Assertions.assertFalse;
25+
import static org.junit.jupiter.api.Assertions.assertTrue;
26+
27+
import java.lang.System.Logger;
28+
import java.lang.System.Logger.Level;
29+
30+
class JavaPlatformLoggerTest {
31+
private final Logger logger = Mockito.mock(Logger.class);
32+
private final JavaPlatformLogger javaPlatformLogger = new JavaPlatformLogger(logger);
33+
34+
@Test
35+
void shouldLogErrorWithMessageAndThrowable() {
36+
Mockito.when(logger.isLoggable(Level.ERROR)).thenReturn(true);
37+
String message = "Hello";
38+
IllegalArgumentException error = new IllegalArgumentException("World");
39+
40+
javaPlatformLogger.error(message, error);
41+
42+
Mockito.verify(logger).log(Level.ERROR, message, error);
43+
}
44+
45+
@Test
46+
void shouldLogInfoWithMessageAndParams() {
47+
Mockito.when(logger.isLoggable(Level.INFO)).thenReturn(true);
48+
String message = "One %s, two %s, three %s";
49+
Object[] params = {"111", "222", "333"};
50+
51+
javaPlatformLogger.info(message, params);
52+
53+
Mockito.verify(logger).log(Level.INFO, "One 111, two 222, three 333");
54+
}
55+
56+
@Test
57+
void shouldLogWarnWithMessageAndParams() {
58+
Mockito.when(logger.isLoggable(Level.WARNING)).thenReturn(true);
59+
String message = "C for %s, d for %s";
60+
Object[] params = {"cat", "dog"};
61+
62+
javaPlatformLogger.warn(message, params);
63+
64+
Mockito.verify(logger).log(Level.WARNING, "C for cat, d for dog");
65+
}
66+
67+
@Test
68+
void shouldLogWarnWithMessageAndThrowable() {
69+
Mockito.when(logger.isLoggable(Level.WARNING)).thenReturn(true);
70+
String message = "Hello";
71+
RuntimeException error = new RuntimeException("World");
72+
73+
javaPlatformLogger.warn(message, error);
74+
75+
Mockito.verify(logger).log(Level.WARNING, message, error);
76+
}
77+
78+
@Test
79+
void shouldLogDebugWithMessageAndParams() {
80+
Mockito.when(logger.isLoggable(Level.DEBUG)).thenReturn(true);
81+
String message = "Hello%s%s!";
82+
Object[] params = {" ", "World"};
83+
84+
javaPlatformLogger.debug(message, params);
85+
86+
Mockito.verify(logger).log(Level.DEBUG, "Hello World!");
87+
}
88+
89+
@Test
90+
void shouldLogTraceWithMessageAndParams() {
91+
Mockito.when(logger.isLoggable(Level.TRACE)).thenReturn(true);
92+
String message = "I'll be %s!";
93+
Object[] params = {"back"};
94+
95+
javaPlatformLogger.trace(message, params);
96+
97+
Mockito.verify(logger).log(Level.TRACE, "I'll be back!");
98+
}
99+
100+
@Test
101+
void shouldCheckIfDebugIsEnabled() {
102+
Mockito.when(logger.isLoggable(Level.DEBUG)).thenReturn(false);
103+
assertFalse(javaPlatformLogger.isDebugEnabled());
104+
105+
Mockito.when(logger.isLoggable(Level.DEBUG)).thenReturn(true);
106+
assertTrue(javaPlatformLogger.isDebugEnabled());
107+
}
108+
109+
@Test
110+
void shouldCheckIfTraceIsEnabled() {
111+
Mockito.when(logger.isLoggable(Level.TRACE)).thenReturn(false);
112+
assertFalse(javaPlatformLogger.isTraceEnabled());
113+
114+
Mockito.when(logger.isLoggable(Level.TRACE)).thenReturn(true);
115+
assertTrue(javaPlatformLogger.isTraceEnabled());
116+
}
117+
}

0 commit comments

Comments
 (0)