From 7e19f8156f8b5098d538366d3b79726b0aae5b68 Mon Sep 17 00:00:00 2001 From: Chengyuan Zhang Date: Mon, 18 May 2020 23:23:25 +0000 Subject: [PATCH 1/9] `NettyClientTransport`: use `getOrCreate` for new instances of the `ChannelLogger` `AttributeKey`. `NettyClientTransport` throws an error when the class is loaded in two separate class-loaders because of some implementation detail with the underlying `AttributeKey` class. Instead of just blowing up when a new `ChannelLogger` key can't be created, this allows multiple, isolated class-loaders in the same JVM to just get the existing key. If this causes issues, this `AttributeKey` should be updated to use a new UUID (or something) each time it is loaded. Improvement: Works with isolated class-loaders. Potential Drawback: Uses the same `ChannelLogger` `AttributeKey` object across multiple, isolated classloaders. --- .../io/grpc/netty/NettyClientTransport.java | 15 ++++++- .../main/java/io/grpc/xds/EnvoyProtoData.java | 30 ++++--------- .../main/java/io/grpc/xds/XdsClientImpl.java | 20 --------- .../java/io/grpc/xds/EnvoyProtoDataTest.java | 42 +++++++++++++++---- .../java/io/grpc/xds/XdsClientImplTest.java | 41 ++++++++++++------ 5 files changed, 87 insertions(+), 61 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index bd00da98384..0fd99e017ba 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -68,7 +68,20 @@ * A Netty-based {@link ConnectionClientTransport} implementation. */ class NettyClientTransport implements ConnectionClientTransport { - static final AttributeKey LOGGER_KEY = AttributeKey.newInstance("channelLogger"); + + /** + * Get the existing {@link ChannelLogger} key in case a separate, isolated class loader has already created + * {@link LOGGER_KEY}. + */ + private final static AttributeKey getOrCreateChannelLogger() { + AttributeKey key = AttributeKey.valueOf("channelLogger"); + if (key == null) { + key = AttributeKey.newInstance("channelLogger"); + } + return key; + } + + static final AttributeKey LOGGER_KEY = getOrCreateChannelLogger(); private final InternalLogId logId; private final Map, ?> channelOptions; diff --git a/xds/src/main/java/io/grpc/xds/EnvoyProtoData.java b/xds/src/main/java/io/grpc/xds/EnvoyProtoData.java index 7e1cd803c5a..329d7c4a74f 100644 --- a/xds/src/main/java/io/grpc/xds/EnvoyProtoData.java +++ b/xds/src/main/java/io/grpc/xds/EnvoyProtoData.java @@ -500,6 +500,9 @@ static StructOrError fromEnvoyProtoRoute(io.envoyproxy.envoy.api.v2.route default: return StructOrError.fromError("Unknown action type: " + proto.getActionCase()); } + if (routeAction == null) { + return null; + } if (routeAction.getErrorDetail() != null) { return StructOrError.fromError( "Invalid route [" + proto.getName() + "]: " + routeAction.getErrorDetail()); @@ -931,16 +934,11 @@ static final class RouteAction { @Nullable private final String cluster; @Nullable - private final String clusterHeader; - @Nullable private final List weightedClusters; @VisibleForTesting - RouteAction( - @Nullable String cluster, @Nullable String clusterHeader, - @Nullable List weightedClusters) { + RouteAction(@Nullable String cluster, @Nullable List weightedClusters) { this.cluster = cluster; - this.clusterHeader = clusterHeader; this.weightedClusters = weightedClusters; } @@ -949,11 +947,6 @@ String getCluster() { return cluster; } - @Nullable - String getClusterHeader() { - return clusterHeader; - } - @Nullable List getWeightedCluster() { return weightedClusters; @@ -969,13 +962,12 @@ public boolean equals(Object o) { } RouteAction that = (RouteAction) o; return Objects.equals(cluster, that.cluster) - && Objects.equals(clusterHeader, that.clusterHeader) - && Objects.equals(weightedClusters, that.weightedClusters); + && Objects.equals(weightedClusters, that.weightedClusters); } @Override public int hashCode() { - return Objects.hash(cluster, clusterHeader, weightedClusters); + return Objects.hash(cluster, weightedClusters); } @Override @@ -984,28 +976,24 @@ public String toString() { if (cluster != null) { toStringHelper.add("cluster", cluster); } - if (clusterHeader != null) { - toStringHelper.add("clusterHeader", clusterHeader); - } if (weightedClusters != null) { toStringHelper.add("weightedClusters", weightedClusters); } return toStringHelper.toString(); } + @Nullable @VisibleForTesting static StructOrError fromEnvoyProtoRouteAction( io.envoyproxy.envoy.api.v2.route.RouteAction proto) { String cluster = null; - String clusterHeader = null; List weightedClusters = null; switch (proto.getClusterSpecifierCase()) { case CLUSTER: cluster = proto.getCluster(); break; case CLUSTER_HEADER: - clusterHeader = proto.getClusterHeader(); - break; + return null; case WEIGHTED_CLUSTERS: List clusterWeights = proto.getWeightedClusters().getClustersList(); @@ -1020,7 +1008,7 @@ static StructOrError fromEnvoyProtoRouteAction( return StructOrError.fromError( "Unknown cluster specifier: " + proto.getClusterSpecifierCase()); } - return StructOrError.fromStruct(new RouteAction(cluster, clusterHeader, weightedClusters)); + return StructOrError.fromStruct(new RouteAction(cluster, weightedClusters)); } } diff --git a/xds/src/main/java/io/grpc/xds/XdsClientImpl.java b/xds/src/main/java/io/grpc/xds/XdsClientImpl.java index ea056755aff..40e9134ebb8 100644 --- a/xds/src/main/java/io/grpc/xds/XdsClientImpl.java +++ b/xds/src/main/java/io/grpc/xds/XdsClientImpl.java @@ -864,30 +864,10 @@ static List populateRoutesInVirtualHost(VirtualHost virtua "Virtual host [" + virtualHost.getName() + "] contains non-default route as the last route"); } - // We only validate the default route unless path matching is enabled. if (!enableExperimentalRouting) { EnvoyProtoData.Route defaultRoute = Iterables.getLast(routes); - if (defaultRoute.getRouteAction().getCluster() == null) { - throw new InvalidProtoDataException( - "Virtual host [" + virtualHost.getName() - + "] default route contains no cluster name"); - } return Collections.singletonList(defaultRoute); } - - // We do more validation if path matching is enabled, but whether every single route is - // required to be valid for grpc is TBD. - // For now we consider the whole list invalid if anything invalid for grpc is found. - // TODO(zdapeng): Fix it if the decision is different from current implementation. - // TODO(zdapeng): Add test for validation. - for (EnvoyProtoData.Route route : routes) { - if (route.getRouteAction().getCluster() == null - && route.getRouteAction().getWeightedCluster() == null) { - throw new InvalidProtoDataException( - "Virtual host [" + virtualHost.getName() - + "] contains route without cluster or weighted cluster"); - } - } return Collections.unmodifiableList(routes); } diff --git a/xds/src/test/java/io/grpc/xds/EnvoyProtoDataTest.java b/xds/src/test/java/io/grpc/xds/EnvoyProtoDataTest.java index 86668c10118..e8afb4b9e29 100644 --- a/xds/src/test/java/io/grpc/xds/EnvoyProtoDataTest.java +++ b/xds/src/test/java/io/grpc/xds/EnvoyProtoDataTest.java @@ -105,7 +105,7 @@ public void convertRoute() { new Route( new RouteMatch( null, "/service/method", null, null, Collections.emptyList()), - new RouteAction("cluster-foo", null, null))); + new RouteAction("cluster-foo", null))); io.envoyproxy.envoy.api.v2.route.Route unsupportedProto = io.envoyproxy.envoy.api.v2.route.Route.newBuilder() @@ -118,6 +118,39 @@ public void convertRoute() { assertThat(unsupportedStruct.getStruct()).isNull(); } + @Test + public void convertRoute_skipWithUnsupportedMatcher() { + io.envoyproxy.envoy.api.v2.route.Route proto = + io.envoyproxy.envoy.api.v2.route.Route.newBuilder() + .setName("ignore me") + .setMatch( + io.envoyproxy.envoy.api.v2.route.RouteMatch.newBuilder() + .setPath("/service/method") + .addQueryParameters( + io.envoyproxy.envoy.api.v2.route.QueryParameterMatcher + .getDefaultInstance())) + .setRoute( + io.envoyproxy.envoy.api.v2.route.RouteAction.newBuilder() + .setCluster("cluster-foo")) + .build(); + assertThat(Route.fromEnvoyProtoRoute(proto)).isNull(); + } + + @Test + public void convertRoute_skipWithUnsupportedAction() { + io.envoyproxy.envoy.api.v2.route.Route proto = + io.envoyproxy.envoy.api.v2.route.Route.newBuilder() + .setName("ignore me") + .setMatch( + io.envoyproxy.envoy.api.v2.route.RouteMatch.newBuilder() + .setPath("/service/method")) + .setRoute( + io.envoyproxy.envoy.api.v2.route.RouteAction.newBuilder() + .setClusterHeader("some cluster header")) + .build(); + assertThat(Route.fromEnvoyProtoRoute(proto)).isNull(); + } + @Test public void isDefaultRoute() { StructOrError struct1 = Route.fromEnvoyProtoRoute(buildSimpleRouteProto("", null)); @@ -315,7 +348,6 @@ public void convertRouteAction() { StructOrError struct1 = RouteAction.fromEnvoyProtoRouteAction(proto1); assertThat(struct1.getErrorDetail()).isNull(); assertThat(struct1.getStruct().getCluster()).isEqualTo("cluster-foo"); - assertThat(struct1.getStruct().getClusterHeader()).isNull(); assertThat(struct1.getStruct().getWeightedCluster()).isNull(); // cluster_specifier = cluster_header @@ -324,10 +356,7 @@ public void convertRouteAction() { .setClusterHeader("cluster-bar") .build(); StructOrError struct2 = RouteAction.fromEnvoyProtoRouteAction(proto2); - assertThat(struct2.getErrorDetail()).isNull(); - assertThat(struct2.getStruct().getCluster()).isNull(); - assertThat(struct2.getStruct().getClusterHeader()).isEqualTo("cluster-bar"); - assertThat(struct2.getStruct().getWeightedCluster()).isNull(); + assertThat(struct2).isNull(); // cluster_specifier = weighted_cluster io.envoyproxy.envoy.api.v2.route.RouteAction proto3 = @@ -342,7 +371,6 @@ public void convertRouteAction() { StructOrError struct3 = RouteAction.fromEnvoyProtoRouteAction(proto3); assertThat(struct3.getErrorDetail()).isNull(); assertThat(struct3.getStruct().getCluster()).isNull(); - assertThat(struct3.getStruct().getClusterHeader()).isNull(); assertThat(struct3.getStruct().getWeightedCluster()) .containsExactly(new ClusterWeight("cluster-baz", 100)); diff --git a/xds/src/test/java/io/grpc/xds/XdsClientImplTest.java b/xds/src/test/java/io/grpc/xds/XdsClientImplTest.java index 67813386167..f67232f6240 100644 --- a/xds/src/test/java/io/grpc/xds/XdsClientImplTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsClientImplTest.java @@ -61,6 +61,7 @@ import io.envoyproxy.envoy.api.v2.core.HealthStatus; import io.envoyproxy.envoy.api.v2.core.Node; import io.envoyproxy.envoy.api.v2.endpoint.ClusterStats; +import io.envoyproxy.envoy.api.v2.route.QueryParameterMatcher; import io.envoyproxy.envoy.api.v2.route.RedirectAction; import io.envoyproxy.envoy.api.v2.route.Route; import io.envoyproxy.envoy.api.v2.route.RouteAction; @@ -727,10 +728,7 @@ public void resolveVirtualHostWithPathMatchingInRdsResponse() { new EnvoyProtoData.RouteMatch( /* prefix= */ null, /* path= */ "/service1/method1"), - new EnvoyProtoData.RouteAction( - "cl1.googleapis.com", - null, - null))); + new EnvoyProtoData.RouteAction("cl1.googleapis.com", null))); assertThat(routes.get(1)).isEqualTo( new EnvoyProtoData.Route( // path match with weighted cluster route @@ -738,7 +736,6 @@ public void resolveVirtualHostWithPathMatchingInRdsResponse() { /* prefix= */ null, /* path= */ "/service2/method2"), new EnvoyProtoData.RouteAction( - null, null, ImmutableList.of( new EnvoyProtoData.ClusterWeight("cl21.googleapis.com", 30), @@ -750,10 +747,7 @@ public void resolveVirtualHostWithPathMatchingInRdsResponse() { new EnvoyProtoData.RouteMatch( /* prefix= */ "/service1/", /* path= */ null), - new EnvoyProtoData.RouteAction( - "cl1.googleapis.com", - null, - null))); + new EnvoyProtoData.RouteAction("cl1.googleapis.com", null))); assertThat(routes.get(3)).isEqualTo( new EnvoyProtoData.Route( // default match with cluster route @@ -761,9 +755,7 @@ public void resolveVirtualHostWithPathMatchingInRdsResponse() { /* prefix= */ "", /* path= */ null), new EnvoyProtoData.RouteAction( - "cluster.googleapis.com", - null, - null))); + "cluster.googleapis.com", null))); } /** @@ -3472,6 +3464,31 @@ public void populateRoutesInVirtualHost_lastRouteIsNotDefaultRoute() { XdsClientImpl.populateRoutesInVirtualHost(virtualHost); } + @Test + public void populateRoutesInVirtualHost_NoUsableRoute() { + VirtualHost virtualHost = + VirtualHost.newBuilder() + .setName("virtualhost00.googleapis.com") // don't care + .addDomains(TARGET_AUTHORITY) + .addRoutes( + // route with unsupported action + Route.newBuilder() + .setRoute(RouteAction.newBuilder().setClusterHeader("cluster header string")) + .setMatch(RouteMatch.newBuilder().setPrefix("/"))) + .addRoutes( + // route with unsupported matcher type + Route.newBuilder() + .setRoute(RouteAction.newBuilder().setCluster("cluster.googleapis.com")) + .setMatch( + RouteMatch.newBuilder() + .setPrefix("/") + .addQueryParameters(QueryParameterMatcher.getDefaultInstance()))) + .build(); + + thrown.expect(XdsClientImpl.InvalidProtoDataException.class); + XdsClientImpl.populateRoutesInVirtualHost(virtualHost); + } + @Test public void messagePrinter_printLdsResponse() { MessagePrinter printer = new MessagePrinter(); From 559dd0fd156cf8312d4b9530e9b579c914874f9f Mon Sep 17 00:00:00 2001 From: Nicholas Titcombe Date: Thu, 21 May 2020 09:33:57 -0700 Subject: [PATCH 2/9] fix line length for linter --- netty/src/main/java/io/grpc/netty/NettyClientTransport.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index 0fd99e017ba..440df7cb594 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -70,8 +70,8 @@ class NettyClientTransport implements ConnectionClientTransport { /** - * Get the existing {@link ChannelLogger} key in case a separate, isolated class loader has already created - * {@link LOGGER_KEY}. + * Get the existing {@link ChannelLogger} key in case a separate, isolated class loader has + * already created {@link LOGGER_KEY}. */ private final static AttributeKey getOrCreateChannelLogger() { AttributeKey key = AttributeKey.valueOf("channelLogger"); From 9d61e278380e2c55acf3b5be7b2a8e1748bd318c Mon Sep 17 00:00:00 2001 From: Nicholas Titcombe Date: Thu, 21 May 2020 09:51:16 -0700 Subject: [PATCH 3/9] make linter happy reorder `final static` -> `static final` --- netty/src/main/java/io/grpc/netty/NettyClientTransport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index 440df7cb594..7c009340a4f 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -73,7 +73,7 @@ class NettyClientTransport implements ConnectionClientTransport { * Get the existing {@link ChannelLogger} key in case a separate, isolated class loader has * already created {@link LOGGER_KEY}. */ - private final static AttributeKey getOrCreateChannelLogger() { + private static final AttributeKey getOrCreateChannelLogger() { AttributeKey key = AttributeKey.valueOf("channelLogger"); if (key == null) { key = AttributeKey.newInstance("channelLogger"); From 24b4e20e653aeb2fa757ffcc7f61b567ad1ac894 Mon Sep 17 00:00:00 2001 From: Nicholas Titcombe Date: Thu, 21 May 2020 10:38:17 -0700 Subject: [PATCH 4/9] make coverage happy too Shortened the null check to get around coverage being upset about 1 line. This lets me avoid making this getOrCreate function public just to test whether AttributeKey works. --- netty/src/main/java/io/grpc/netty/NettyClientTransport.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index 7c009340a4f..87f9eb42a13 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -75,10 +75,7 @@ class NettyClientTransport implements ConnectionClientTransport { */ private static final AttributeKey getOrCreateChannelLogger() { AttributeKey key = AttributeKey.valueOf("channelLogger"); - if (key == null) { - key = AttributeKey.newInstance("channelLogger"); - } - return key; + return key != null ? key : AttributeKey.newInstance("channelLogger"); } static final AttributeKey LOGGER_KEY = getOrCreateChannelLogger(); From 9f31da47634fbd6a70d37d8df1e304e8f4cba177 Mon Sep 17 00:00:00 2001 From: Nicholas Titcombe Date: Thu, 21 May 2020 11:26:57 -0700 Subject: [PATCH 5/9] make the compiler happy --- netty/src/main/java/io/grpc/netty/NettyClientTransport.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index 87f9eb42a13..60f6c79315a 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -74,8 +74,10 @@ class NettyClientTransport implements ConnectionClientTransport { * already created {@link LOGGER_KEY}. */ private static final AttributeKey getOrCreateChannelLogger() { - AttributeKey key = AttributeKey.valueOf("channelLogger"); - return key != null ? key : AttributeKey.newInstance("channelLogger"); + String name = "channelLogger"; + AttributeKey key = AttributeKey.exists(name) + ? AttributeKey.valueOf(name) : AttributeKey.newInstance(name); + return key; } static final AttributeKey LOGGER_KEY = getOrCreateChannelLogger(); From b6f49d54ca8cb8f18181c4168639889e4ea23a41 Mon Sep 17 00:00:00 2001 From: Nicholas Titcombe Date: Thu, 21 May 2020 11:56:37 -0700 Subject: [PATCH 6/9] maybe make compiler happy? --- netty/src/main/java/io/grpc/netty/NettyClientTransport.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index 60f6c79315a..0cb5109df70 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -75,9 +75,8 @@ class NettyClientTransport implements ConnectionClientTransport { */ private static final AttributeKey getOrCreateChannelLogger() { String name = "channelLogger"; - AttributeKey key = AttributeKey.exists(name) - ? AttributeKey.valueOf(name) : AttributeKey.newInstance(name); - return key; + return AttributeKey.exists(name) ? + AttributeKey.valueOf(name) : AttributeKey.newInstance(name); } static final AttributeKey LOGGER_KEY = getOrCreateChannelLogger(); From 193f2b1c4e8d1afd14a928278b04ee7aeb1c0f80 Mon Sep 17 00:00:00 2001 From: Nicholas Titcombe Date: Thu, 21 May 2020 12:08:08 -0700 Subject: [PATCH 7/9] make coverage sad and make compiler happy --- .../src/main/java/io/grpc/netty/NettyClientTransport.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index 0cb5109df70..9a7f7bbf283 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -74,9 +74,11 @@ class NettyClientTransport implements ConnectionClientTransport { * already created {@link LOGGER_KEY}. */ private static final AttributeKey getOrCreateChannelLogger() { - String name = "channelLogger"; - return AttributeKey.exists(name) ? - AttributeKey.valueOf(name) : AttributeKey.newInstance(name); + AttributeKey key = AttributeKey.valueOf("channelLogger") + if (key == null) { + key = AttributeKey.newInstance("channelLogger"); + } + return key; } static final AttributeKey LOGGER_KEY = getOrCreateChannelLogger(); From ff98c2aaa270beb8112a1731ec4c426c6843aaba Mon Sep 17 00:00:00 2001 From: Nicholas Titcombe Date: Thu, 21 May 2020 12:09:57 -0700 Subject: [PATCH 8/9] Put semicolon in the end of the line --- netty/src/main/java/io/grpc/netty/NettyClientTransport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index 9a7f7bbf283..83978f3d636 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -74,7 +74,7 @@ class NettyClientTransport implements ConnectionClientTransport { * already created {@link LOGGER_KEY}. */ private static final AttributeKey getOrCreateChannelLogger() { - AttributeKey key = AttributeKey.valueOf("channelLogger") + AttributeKey key = AttributeKey.valueOf("channelLogger"); if (key == null) { key = AttributeKey.newInstance("channelLogger"); } From e6da351f7895be3ca149772dee618f45a7c4a392 Mon Sep 17 00:00:00 2001 From: Nicholas Titcombe Date: Thu, 21 May 2020 12:11:17 -0700 Subject: [PATCH 9/9] remove leftover code from previous commit (woops) --- netty/src/main/java/io/grpc/netty/NettyClientTransport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java index 83978f3d636..7c009340a4f 100644 --- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java +++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java @@ -76,7 +76,7 @@ class NettyClientTransport implements ConnectionClientTransport { private static final AttributeKey getOrCreateChannelLogger() { AttributeKey key = AttributeKey.valueOf("channelLogger"); if (key == null) { - key = AttributeKey.newInstance("channelLogger"); + key = AttributeKey.newInstance("channelLogger"); } return key; }