Skip to content

Commit b593be7

Browse files
committed
Use FQDN in RFC5424 Layout (+review #2853)
Since RFC5424 specifies that the [`HOSTNAME`](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.4) field should contain the FQDN of the current host, we replace replace the usage of `InetAddress.getHostName()` with `InetAddress.getCanonicalHostName()`. Closes #1740.
1 parent 9348429 commit b593be7

File tree

7 files changed

+163
-73
lines changed

7 files changed

+163
-73
lines changed

log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/Rfc5424LayoutTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616
*/
1717
package org.apache.logging.log4j.core.layout;
1818

19+
import static org.assertj.core.api.Assertions.assertThat;
1920
import static org.junit.jupiter.api.Assertions.assertEquals;
2021
import static org.junit.jupiter.api.Assertions.assertFalse;
22+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
2123
import static org.junit.jupiter.api.Assertions.assertNotNull;
2224
import static org.junit.jupiter.api.Assertions.assertNull;
2325
import static org.junit.jupiter.api.Assertions.assertTrue;
2426
import static org.junit.jupiter.api.Assertions.fail;
2527

28+
import java.net.InetAddress;
29+
import java.net.UnknownHostException;
2630
import java.util.ArrayList;
2731
import java.util.Arrays;
2832
import java.util.List;
@@ -751,7 +755,7 @@ public void testLayoutBuilderDefaultValues() {
751755
.withConfigurationNode(new Node())
752756
.withConfiguration(new DefaultConfiguration())
753757
.build();
754-
assertTrue(obj instanceof Rfc5424Layout);
758+
assertInstanceOf(Rfc5424Layout.class, obj);
755759
checkDefaultValues((Rfc5424Layout) obj);
756760
}
757761

@@ -781,4 +785,11 @@ void testLayoutBuilderInvalidEids(final String eid) {
781785

782786
assertNull(layout);
783787
}
788+
789+
@Test
790+
void testFQDN() throws UnknownHostException {
791+
final String fqdn = InetAddress.getLocalHost().getCanonicalHostName();
792+
final Rfc5424Layout layout = Rfc5424Layout.newBuilder().build();
793+
assertThat(layout.getLocalHostName()).isEqualTo(fqdn);
794+
}
784795
}

log4j-core-test/src/test/java/org/apache/logging/log4j/core/util/NetUtilsTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
package org.apache.logging.log4j.core.util;
1818

19+
import static org.assertj.core.api.Assertions.assertThat;
1920
import static org.junit.jupiter.api.Assertions.assertEquals;
2021
import static org.junit.jupiter.api.Assertions.assertNotNull;
2122

@@ -70,4 +71,10 @@ public void testToUriWindowsAbsolutePath() {
7071
assertNotNull(uri, "The URI should not be null.");
7172
assertEquals("file:/D:/path/to/something/on/windows", uri.toString(), "The URI is not correct.");
7273
}
74+
75+
@Test
76+
public void testCanonicalHostName() {
77+
// If this fails the host might be misconfigured
78+
assertThat(NetUtils.getCanonicalLocalHostname()).contains(".");
79+
}
7380
}

log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public SyslogAppender build() {
131131
.setExceptionPattern(exceptionPattern)
132132
.setUseTLSMessageFormat(useTlsMessageFormat)
133133
.setLoggerFields(loggerFields)
134-
.setConfig(configuration)
134+
.setConfiguration(configuration)
135135
.build()
136136
:
137137
// @formatter:off

log4j-core/src/main/java/org/apache/logging/log4j/core/layout/Rfc5424Layout.java

Lines changed: 108 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@
3636
import org.apache.logging.log4j.core.config.Configuration;
3737
import org.apache.logging.log4j.core.config.Node;
3838
import org.apache.logging.log4j.core.config.plugins.Plugin;
39-
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
40-
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
39+
import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
40+
import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
4141
import org.apache.logging.log4j.core.config.plugins.PluginElement;
42-
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
4342
import org.apache.logging.log4j.core.layout.internal.ExcludeChecker;
4443
import org.apache.logging.log4j.core.layout.internal.IncludeChecker;
4544
import org.apache.logging.log4j.core.layout.internal.ListChecker;
@@ -167,7 +166,7 @@ private Rfc5424Layout(
167166
this.appName = appName;
168167
this.messageId = messageId;
169168
this.useTlsMessageFormat = useTLSMessageFormat;
170-
this.localHostName = NetUtils.getLocalHostname();
169+
this.localHostName = NetUtils.getCanonicalLocalHostname();
171170
ListChecker checker = null;
172171
if (excludes != null) {
173172
final String[] array = excludes.split(Patterns.COMMA_SEPARATOR);
@@ -642,80 +641,122 @@ public String toString() {
642641
* @return An Rfc5424Layout.
643642
* @deprecated Use {@link Rfc5424LayoutBuilder instead}
644643
*/
645-
@PluginFactory
644+
@Deprecated
646645
public static Rfc5424Layout createLayout(
647-
// @formatter:off
648-
@PluginAttribute(value = "facility", defaultString = "LOCAL0") final Facility facility,
649-
@PluginAttribute("id") final String id,
650-
@PluginAttribute(value = "enterpriseNumber", defaultInt = DEFAULT_ENTERPRISE_NUMBER)
651-
final int enterpriseNumber,
652-
@PluginAttribute(value = "includeMDC", defaultBoolean = true) final boolean includeMDC,
653-
@PluginAttribute(value = "mdcId", defaultString = DEFAULT_MDCID) final String mdcId,
654-
@PluginAttribute("mdcPrefix") final String mdcPrefix,
655-
@PluginAttribute("eventPrefix") final String eventPrefix,
656-
@PluginAttribute(value = "newLine") final boolean newLine,
657-
@PluginAttribute("newLineEscape") final String escapeNL,
658-
@PluginAttribute("appName") final String appName,
659-
@PluginAttribute("messageId") final String msgId,
660-
@PluginAttribute("mdcExcludes") final String excludes,
661-
@PluginAttribute("mdcIncludes") String includes,
662-
@PluginAttribute("mdcRequired") final String required,
663-
@PluginAttribute("exceptionPattern") final String exceptionPattern,
664-
// RFC 5425
665-
@PluginAttribute(value = "useTlsMessageFormat") final boolean useTlsMessageFormat,
666-
@PluginElement("LoggerFields") final LoggerFields[] loggerFields,
667-
@PluginConfiguration final Configuration config) {
668-
// @formatter:on
646+
final Facility facility,
647+
final String id,
648+
final int enterpriseNumber,
649+
final boolean includeMDC,
650+
final String mdcId,
651+
final String mdcPrefix,
652+
final String eventPrefix,
653+
final boolean newLine,
654+
final String escapeNL,
655+
final String appName,
656+
final String msgId,
657+
final String excludes,
658+
String includes,
659+
final String required,
660+
final String exceptionPattern,
661+
final boolean useTlsMessageFormat,
662+
final LoggerFields[] loggerFields,
663+
final Configuration config) {
669664
if (includes != null && excludes != null) {
670665
LOGGER.error("mdcIncludes and mdcExcludes are mutually exclusive. Includes wil be ignored");
671666
includes = null;
672667
}
673668

674-
return new Rfc5424Layout(
675-
config,
676-
facility,
677-
id,
678-
String.valueOf(enterpriseNumber),
679-
includeMDC,
680-
newLine,
681-
escapeNL,
682-
mdcId,
683-
mdcPrefix,
684-
eventPrefix,
685-
appName,
686-
msgId,
687-
excludes,
688-
includes,
689-
required,
690-
StandardCharsets.UTF_8,
691-
exceptionPattern,
692-
useTlsMessageFormat,
693-
loggerFields);
694-
}
695-
696-
public static class Rfc5424LayoutBuilder {
697-
private Configuration config;
669+
return newBuilder()
670+
.setConfiguration(config)
671+
.setFacility(facility)
672+
.setId(id)
673+
.setEin(String.valueOf(enterpriseNumber))
674+
.setIncludeMDC(includeMDC)
675+
.setIncludeNL(newLine)
676+
.setEscapeNL(escapeNL)
677+
.setMdcId(mdcId)
678+
.setMdcPrefix(mdcPrefix)
679+
.setEventPrefix(eventPrefix)
680+
.setAppName(appName)
681+
.setMessageId(msgId)
682+
.setExcludes(excludes)
683+
.setIncludes(includes)
684+
.setRequired(required)
685+
.setCharset(StandardCharsets.UTF_8)
686+
.setExceptionPattern(exceptionPattern)
687+
.setUseTLSMessageFormat(useTlsMessageFormat)
688+
.setLoggerFields(loggerFields)
689+
.build();
690+
}
691+
692+
@PluginBuilderFactory
693+
public static Rfc5424LayoutBuilder newBuilder() {
694+
return new Rfc5424LayoutBuilder();
695+
}
696+
697+
public static class Rfc5424LayoutBuilder extends AbstractStringLayout.Builder<Rfc5424LayoutBuilder>
698+
implements org.apache.logging.log4j.core.util.Builder<Rfc5424Layout> {
699+
700+
@PluginBuilderAttribute
698701
private Facility facility = Facility.LOCAL0;
702+
703+
@PluginBuilderAttribute
699704
private String id;
705+
706+
@PluginBuilderAttribute
700707
private String ein = String.valueOf(DEFAULT_ENTERPRISE_NUMBER);
708+
709+
@PluginBuilderAttribute
710+
private Integer enterpriseNumber;
711+
712+
@PluginBuilderAttribute
701713
private boolean includeMDC = true;
714+
715+
@PluginBuilderAttribute
702716
private boolean includeNL;
717+
718+
@PluginBuilderAttribute
703719
private String escapeNL;
720+
721+
@PluginBuilderAttribute
704722
private String mdcId = DEFAULT_MDCID;
723+
724+
@PluginBuilderAttribute
705725
private String mdcPrefix;
726+
727+
@PluginBuilderAttribute
706728
private String eventPrefix;
729+
730+
@PluginBuilderAttribute
707731
private String appName;
732+
733+
@PluginBuilderAttribute
708734
private String messageId;
735+
736+
@PluginBuilderAttribute
709737
private String excludes;
738+
739+
@PluginBuilderAttribute
710740
private String includes;
741+
742+
@PluginBuilderAttribute
711743
private String required;
712-
private Charset charset;
744+
745+
@PluginBuilderAttribute
713746
private String exceptionPattern;
747+
748+
@PluginBuilderAttribute
714749
private boolean useTLSMessageFormat;
750+
751+
@PluginElement(value = "loggerFields")
715752
private LoggerFields[] loggerFields;
716753

754+
/**
755+
* @deprecated Since 2.24.0 use {@link #setConfiguration} instead.
756+
*/
757+
@Deprecated
717758
public Rfc5424LayoutBuilder setConfig(final Configuration config) {
718-
this.config = config;
759+
setConfiguration(config);
719760
return this;
720761
}
721762

@@ -789,9 +830,9 @@ public Rfc5424LayoutBuilder setRequired(final String required) {
789830
return this;
790831
}
791832

833+
// Kept for binary compatibility
792834
public Rfc5424LayoutBuilder setCharset(final Charset charset) {
793-
this.charset = charset;
794-
return this;
835+
return super.setCharset(charset);
795836
}
796837

797838
public Rfc5424LayoutBuilder setExceptionPattern(final String exceptionPattern) {
@@ -809,19 +850,24 @@ public Rfc5424LayoutBuilder setLoggerFields(final LoggerFields[] loggerFields) {
809850
return this;
810851
}
811852

853+
@Override
812854
public Rfc5424Layout build() {
813855
if (includes != null && excludes != null) {
814856
LOGGER.error("mdcIncludes and mdcExcludes are mutually exclusive. Includes wil be ignored");
815857
includes = null;
816858
}
817859

860+
if (enterpriseNumber != null) {
861+
ein = String.valueOf(enterpriseNumber);
862+
}
818863
if (ein != null && !ENTERPRISE_ID_PATTERN.matcher(ein).matches()) {
819864
LOGGER.warn(String.format("provided EID %s is not in valid format!", ein));
820865
return null;
821866
}
867+
final Charset charset = getCharset();
822868

823869
return new Rfc5424Layout(
824-
config,
870+
getConfiguration(),
825871
facility,
826872
id,
827873
ein,
@@ -836,7 +882,7 @@ public Rfc5424Layout build() {
836882
excludes,
837883
includes,
838884
required,
839-
charset,
885+
charset != null ? charset : StandardCharsets.UTF_8,
840886
exceptionPattern,
841887
useTLSMessageFormat,
842888
loggerFields);
@@ -926,4 +972,9 @@ public boolean isIncludeMdc() {
926972
public String getMdcId() {
927973
return mdcId;
928974
}
975+
976+
// Used in tests
977+
String getLocalHostName() {
978+
return localHostName;
979+
}
929980
}

log4j-core/src/main/java/org/apache/logging/log4j/core/layout/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* {@link org.apache.logging.log4j.core.Layout#ELEMENT_TYPE layout}.
2323
*/
2424
@Export
25-
@Version("2.20.1")
25+
@Version("2.24.0")
2626
package org.apache.logging.log4j.core.layout;
2727

2828
import org.osgi.annotation.bundle.Export;

log4j-core/src/main/java/org/apache/logging/log4j/core/util/NetUtils.java

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.Arrays;
3131
import java.util.Enumeration;
3232
import java.util.List;
33+
import java.util.function.Function;
3334
import org.apache.logging.log4j.Logger;
3435
import org.apache.logging.log4j.status.StatusLogger;
3536

@@ -52,23 +53,35 @@ private NetUtils() {
5253
* @return String the name of the local host
5354
*/
5455
public static String getLocalHostname() {
56+
return getHostname(InetAddress::getHostName);
57+
}
58+
59+
/**
60+
* This method gets the FQDN of the machine we are running on.
61+
* It returns {@value UNKNOWN_LOCALHOST} if the host name cannot be found.
62+
*
63+
* @return The canonical name of the local host; or {@value UNKNOWN_LOCALHOST}, if cannot be found.
64+
*/
65+
public static String getCanonicalLocalHostname() {
66+
return getHostname(InetAddress::getCanonicalHostName);
67+
}
68+
69+
private static String getHostname(final Function<? super InetAddress, ? extends String> callback) {
5570
try {
56-
final InetAddress addr = InetAddress.getLocalHost();
57-
return addr == null ? UNKNOWN_LOCALHOST : addr.getHostName();
71+
final InetAddress address = InetAddress.getLocalHost();
72+
return address == null ? UNKNOWN_LOCALHOST : callback.apply(address);
5873
} catch (final UnknownHostException uhe) {
5974
try {
6075
final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
61-
if (interfaces != null) {
62-
while (interfaces.hasMoreElements()) {
63-
final NetworkInterface nic = interfaces.nextElement();
64-
final Enumeration<InetAddress> addresses = nic.getInetAddresses();
65-
while (addresses.hasMoreElements()) {
66-
final InetAddress address = addresses.nextElement();
67-
if (!address.isLoopbackAddress()) {
68-
final String hostname = address.getHostName();
69-
if (hostname != null) {
70-
return hostname;
71-
}
76+
while (interfaces.hasMoreElements()) {
77+
final NetworkInterface nic = interfaces.nextElement();
78+
final Enumeration<InetAddress> addresses = nic.getInetAddresses();
79+
while (addresses.hasMoreElements()) {
80+
final InetAddress address = addresses.nextElement();
81+
if (!address.isLoopbackAddress()) {
82+
final String hostname = callback.apply(address);
83+
if (hostname != null) {
84+
return hostname;
7285
}
7386
}
7487
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="https://logging.apache.org/xml/ns"
4+
xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
5+
type="added">
6+
<issue id="1740" link="https://github.com/apache/logging-log4j2/issues/1740"/>
7+
<description format="asciidoc">Add `useFqdn` configuration attribute to RFC5424 Layout.</description>
8+
</entry>

0 commit comments

Comments
 (0)