Expose a LoggingDnsQueryLifeCycleObserverFactory (#10490)

Expose a LoggingDnsQueryLifeCycleObserverFactory

Motivation:
 There is a use case for having logging in the DnsNameResolver, similar to the LoggingHandler.
 Previously, one could set `traceEnabled` on the DnsNameResolverBuilder, but this is not very configurable.
 Specifically, the log level and the logger context cannot be changed.

Modification:
 Expose a LoggingDnsQueryLifeCycleObserverFactory, that permit changing the log-level
 and logger context.

Result:
 It is now possible to get logging in the DnsNameResolver at a custom log level and logger,
 without very much effort.

Fixes #10485
This commit is contained in:
Chris Vest 2020-08-19 20:22:38 +02:00 committed by GitHub
parent 830fc0d660
commit 0bbe4ce9fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 97 additions and 49 deletions

View File

@ -63,6 +63,11 @@
<artifactId>netty-codec-dns</artifactId> <artifactId>netty-codec-dns</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-handler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.directory.server</groupId> <groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-protocol-dns</artifactId> <artifactId>apacheds-protocol-dns</artifactId>

View File

@ -399,8 +399,8 @@ public class DnsNameResolver extends InetNameResolver {
this.cnameCache = checkNotNull(cnameCache, "cnameCache"); this.cnameCache = checkNotNull(cnameCache, "cnameCache");
this.dnsQueryLifecycleObserverFactory = traceEnabled ? this.dnsQueryLifecycleObserverFactory = traceEnabled ?
dnsQueryLifecycleObserverFactory instanceof NoopDnsQueryLifecycleObserverFactory ? dnsQueryLifecycleObserverFactory instanceof NoopDnsQueryLifecycleObserverFactory ?
new TraceDnsQueryLifeCycleObserverFactory() : new LoggingDnsQueryLifeCycleObserverFactory() :
new BiDnsQueryLifecycleObserverFactory(new TraceDnsQueryLifeCycleObserverFactory(), new BiDnsQueryLifecycleObserverFactory(new LoggingDnsQueryLifeCycleObserverFactory(),
dnsQueryLifecycleObserverFactory) : dnsQueryLifecycleObserverFactory) :
checkNotNull(dnsQueryLifecycleObserverFactory, "dnsQueryLifecycleObserverFactory"); checkNotNull(dnsQueryLifecycleObserverFactory, "dnsQueryLifecycleObserverFactory");
this.searchDomains = searchDomains != null ? searchDomains.clone() : DEFAULT_SEARCH_DOMAINS; this.searchDomains = searchDomains != null ? searchDomains.clone() : DEFAULT_SEARCH_DOMAINS;

View File

@ -324,7 +324,10 @@ public final class DnsNameResolverBuilder {
* *
* @param traceEnabled true if trace is enabled * @param traceEnabled true if trace is enabled
* @return {@code this} * @return {@code this}
* @deprecated Prefer to {@linkplain #dnsQueryLifecycleObserverFactory(DnsQueryLifecycleObserverFactory) configure}
* a {@link LoggingDnsQueryLifeCycleObserverFactory} instead.
*/ */
@Deprecated
public DnsNameResolverBuilder traceEnabled(boolean traceEnabled) { public DnsNameResolverBuilder traceEnabled(boolean traceEnabled) {
this.traceEnabled = traceEnabled; this.traceEnabled = traceEnabled;
return this; return this;

View File

@ -0,0 +1,85 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.resolver.dns;
import io.netty.handler.codec.dns.DnsQuestion;
import io.netty.handler.logging.LogLevel;
import io.netty.util.internal.logging.InternalLogLevel;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
/**
* A {@link DnsQueryLifecycleObserverFactory} that enables detailed logging in the {@link DnsNameResolver}.
* <p>
* When {@linkplain DnsNameResolverBuilder#dnsQueryLifecycleObserverFactory(DnsQueryLifecycleObserverFactory)
* configured on the resolver}, detailed trace information will be generated so that it is easier to understand the
* cause of resolution failure.
*/
public final class LoggingDnsQueryLifeCycleObserverFactory implements DnsQueryLifecycleObserverFactory {
private static final InternalLogger DEFAULT_LOGGER =
InternalLoggerFactory.getInstance(LoggingDnsQueryLifeCycleObserverFactory.class);
private final InternalLogger logger;
private final InternalLogLevel level;
/**
* Create {@link DnsQueryLifecycleObserver} instances that log events at the default {@link LogLevel#DEBUG} level.
*/
public LoggingDnsQueryLifeCycleObserverFactory() {
this(LogLevel.DEBUG);
}
/**
* Create {@link DnsQueryLifecycleObserver} instances that log events at the given log level.
* @param level The log level to use for logging resolver events.
*/
public LoggingDnsQueryLifeCycleObserverFactory(LogLevel level) {
this.level = checkAndConvertLevel(level);
logger = DEFAULT_LOGGER;
}
/**
* Create {@link DnsQueryLifecycleObserver} instances that log events to a logger with the given class context,
* at the given log level.
* @param classContext The class context for the logger to use.
* @param level The log level to use for logging resolver events.
*/
public LoggingDnsQueryLifeCycleObserverFactory(Class<?> classContext, LogLevel level) {
this.level = checkAndConvertLevel(level);
logger = InternalLoggerFactory.getInstance(checkNotNull(classContext, "classContext"));
}
/**
* Create {@link DnsQueryLifecycleObserver} instances that log events to a logger with the given name context,
* at the given log level.
* @param name The name for the logger to use.
* @param level The log level to use for logging resolver events.
*/
public LoggingDnsQueryLifeCycleObserverFactory(String name, LogLevel level) {
this.level = checkAndConvertLevel(level);
logger = InternalLoggerFactory.getInstance(checkNotNull(name, "name"));
}
private static InternalLogLevel checkAndConvertLevel(LogLevel level) {
return checkNotNull(level, "level").toInternalLevel();
}
@Override
public DnsQueryLifecycleObserver newDnsQueryLifecycleObserver(DnsQuestion question) {
return new LoggingDnsQueryLifecycleObserver(question, logger, level);
}
}

View File

@ -26,13 +26,13 @@ import java.util.List;
import static io.netty.util.internal.ObjectUtil.checkNotNull; import static io.netty.util.internal.ObjectUtil.checkNotNull;
final class TraceDnsQueryLifecycleObserver implements DnsQueryLifecycleObserver { final class LoggingDnsQueryLifecycleObserver implements DnsQueryLifecycleObserver {
private final InternalLogger logger; private final InternalLogger logger;
private final InternalLogLevel level; private final InternalLogLevel level;
private final DnsQuestion question; private final DnsQuestion question;
private InetSocketAddress dnsServerAddress; private InetSocketAddress dnsServerAddress;
TraceDnsQueryLifecycleObserver(DnsQuestion question, InternalLogger logger, InternalLogLevel level) { LoggingDnsQueryLifecycleObserver(DnsQuestion question, InternalLogger logger, InternalLogLevel level) {
this.question = checkNotNull(question, "question"); this.question = checkNotNull(question, "question");
this.logger = checkNotNull(logger, "logger"); this.logger = checkNotNull(logger, "logger");
this.level = checkNotNull(level, "level"); this.level = checkNotNull(level, "level");

View File

@ -1,45 +0,0 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.resolver.dns;
import io.netty.handler.codec.dns.DnsQuestion;
import io.netty.util.internal.logging.InternalLogLevel;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
final class TraceDnsQueryLifeCycleObserverFactory implements DnsQueryLifecycleObserverFactory {
private static final InternalLogger DEFAULT_LOGGER =
InternalLoggerFactory.getInstance(TraceDnsQueryLifeCycleObserverFactory.class);
private static final InternalLogLevel DEFAULT_LEVEL = InternalLogLevel.DEBUG;
private final InternalLogger logger;
private final InternalLogLevel level;
TraceDnsQueryLifeCycleObserverFactory() {
this(DEFAULT_LOGGER, DEFAULT_LEVEL);
}
TraceDnsQueryLifeCycleObserverFactory(InternalLogger logger, InternalLogLevel level) {
this.logger = checkNotNull(logger, "logger");
this.level = checkNotNull(level, "level");
}
@Override
public DnsQueryLifecycleObserver newDnsQueryLifecycleObserver(DnsQuestion question) {
return new TraceDnsQueryLifecycleObserver(question, logger, level);
}
}