Skip to content

Commit ecb5e7a

Browse files
KAFKA-15831: KIP-1000 protocol and admin client
1 parent 270be2d commit ecb5e7a

19 files changed

Lines changed: 540 additions & 24 deletions

clients/src/main/java/org/apache/kafka/clients/admin/Admin.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,26 @@ default FenceProducersResult fenceProducers(Collection<String> transactionalIds)
16631663
FenceProducersResult fenceProducers(Collection<String> transactionalIds,
16641664
FenceProducersOptions options);
16651665

1666+
/**
1667+
* List the client metrics configuration resources available in the cluster.
1668+
*
1669+
* @param options The options to use when listing the client metrics resources.
1670+
* @return The ListClientMetricsResourcesResult.
1671+
*/
1672+
ListClientMetricsResourcesResult listClientMetricsResources(ListClientMetricsResourcesOptions options);
1673+
1674+
/**
1675+
* List the client metrics configuration resources available in the cluster with the default options.
1676+
* <p>
1677+
* This is a convenience method for {@link #listClientMetricsResources(ListClientMetricsResourcesOptions)}
1678+
* with default options. See the overload for more details.
1679+
*
1680+
* @return The ListClientMetricsResourcesResult.
1681+
*/
1682+
default ListClientMetricsResourcesResult listClientMetricsResources() {
1683+
return listClientMetricsResources(new ListClientMetricsResourcesOptions());
1684+
}
1685+
16661686
/**
16671687
* Determines the client's unique client instance ID used for telemetry. This ID is unique to
16681688
* this specific client instance and will not change after it is initially generated.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.kafka.clients.admin;
18+
19+
import org.apache.kafka.common.annotation.InterfaceStability;
20+
21+
import java.util.Objects;
22+
23+
@InterfaceStability.Evolving
24+
public class ClientMetricsResourceListing {
25+
private final String name;
26+
27+
public ClientMetricsResourceListing(String name) {
28+
this.name = name;
29+
}
30+
31+
public String name() {
32+
return name;
33+
}
34+
35+
@Override
36+
public boolean equals(Object o) {
37+
if (this == o) return true;
38+
if (o == null || getClass() != o.getClass()) return false;
39+
ClientMetricsResourceListing that = (ClientMetricsResourceListing) o;
40+
return Objects.equals(name, that.name);
41+
}
42+
43+
@Override
44+
public int hashCode() {
45+
return Objects.hash(name);
46+
}
47+
48+
@Override
49+
public String toString() {
50+
return "ClientMetricsResourceListing(" +
51+
"name='" + name +
52+
')';
53+
}
54+
}

clients/src/main/java/org/apache/kafka/clients/admin/ForwardingAdmin.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@ public FenceProducersResult fenceProducers(Collection<String> transactionalIds,
278278
return delegate.fenceProducers(transactionalIds, options);
279279
}
280280

281+
@Override
282+
public ListClientMetricsResourcesResult listClientMetricsResources(ListClientMetricsResourcesOptions options) {
283+
return delegate.listClientMetricsResources(options);
284+
}
285+
281286
@Override
282287
public Uuid clientInstanceId(Duration timeout) {
283288
return delegate.clientInstanceId(timeout);

clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
import org.apache.kafka.common.message.DescribeUserScramCredentialsResponseData;
142142
import org.apache.kafka.common.message.ExpireDelegationTokenRequestData;
143143
import org.apache.kafka.common.message.LeaveGroupRequestData.MemberIdentity;
144+
import org.apache.kafka.common.message.ListClientMetricsResourcesRequestData;
144145
import org.apache.kafka.common.message.ListGroupsRequestData;
145146
import org.apache.kafka.common.message.ListGroupsResponseData;
146147
import org.apache.kafka.common.message.ListPartitionReassignmentsRequestData;
@@ -210,6 +211,8 @@
210211
import org.apache.kafka.common.requests.IncrementalAlterConfigsRequest;
211212
import org.apache.kafka.common.requests.IncrementalAlterConfigsResponse;
212213
import org.apache.kafka.common.requests.JoinGroupRequest;
214+
import org.apache.kafka.common.requests.ListClientMetricsResourcesRequest;
215+
import org.apache.kafka.common.requests.ListClientMetricsResourcesResponse;
213216
import org.apache.kafka.common.requests.ListGroupsRequest;
214217
import org.apache.kafka.common.requests.ListGroupsResponse;
215218
import org.apache.kafka.common.requests.ListOffsetsRequest;
@@ -4385,6 +4388,36 @@ public FenceProducersResult fenceProducers(Collection<String> transactionalIds,
43854388
return new FenceProducersResult(future.all());
43864389
}
43874390

4391+
@Override
4392+
public ListClientMetricsResourcesResult listClientMetricsResources(ListClientMetricsResourcesOptions options) {
4393+
final long now = time.milliseconds();
4394+
final KafkaFutureImpl<Collection<ClientMetricsResourceListing>> future = new KafkaFutureImpl<>();
4395+
runnable.call(new Call("listClientMetricsResources", calcDeadlineMs(now, options.timeoutMs()),
4396+
new LeastLoadedNodeProvider()) {
4397+
4398+
@Override
4399+
ListClientMetricsResourcesRequest.Builder createRequest(int timeoutMs) {
4400+
return new ListClientMetricsResourcesRequest.Builder(new ListClientMetricsResourcesRequestData());
4401+
}
4402+
4403+
@Override
4404+
void handleResponse(AbstractResponse abstractResponse) {
4405+
ListClientMetricsResourcesResponse response = (ListClientMetricsResourcesResponse) abstractResponse;
4406+
if (response.error().isFailure()) {
4407+
future.completeExceptionally(response.error().exception());
4408+
} else {
4409+
future.complete(response.clientMetricsResources());
4410+
}
4411+
}
4412+
4413+
@Override
4414+
void handleFailure(Throwable throwable) {
4415+
future.completeExceptionally(throwable);
4416+
}
4417+
}, now);
4418+
return new ListClientMetricsResourcesResult(future);
4419+
}
4420+
43884421
@Override
43894422
public Uuid clientInstanceId(Duration timeout) {
43904423
throw new UnsupportedOperationException();
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.kafka.clients.admin;
19+
20+
import org.apache.kafka.common.annotation.InterfaceStability;
21+
22+
/**
23+
* Options for {@link Admin#listClientMetricsResources()}.
24+
*
25+
* The API of this class is evolving, see {@link Admin} for details.
26+
*/
27+
@InterfaceStability.Evolving
28+
public class ListClientMetricsResourcesOptions extends AbstractOptions<ListClientMetricsResourcesOptions> {
29+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.kafka.clients.admin;
19+
20+
import org.apache.kafka.common.KafkaFuture;
21+
import org.apache.kafka.common.annotation.InterfaceStability;
22+
import org.apache.kafka.common.internals.KafkaFutureImpl;
23+
24+
import java.util.Collection;
25+
26+
/**
27+
* The result of the {@link Admin#listClientMetricsResources()} call.
28+
* <p>
29+
* The API of this class is evolving, see {@link Admin} for details.
30+
*/
31+
@InterfaceStability.Evolving
32+
public class ListClientMetricsResourcesResult {
33+
private final KafkaFuture<Collection<ClientMetricsResourceListing>> future;
34+
35+
ListClientMetricsResourcesResult(KafkaFuture<Collection<ClientMetricsResourceListing>> future) {
36+
this.future = future;
37+
}
38+
39+
/**
40+
* Returns a future that yields either an exception, or the full set of client metrics
41+
* listings.
42+
*
43+
* In the event of a failure, the future yields nothing but the first exception which
44+
* occurred.
45+
*/
46+
public KafkaFuture<Collection<ClientMetricsResourceListing>> all() {
47+
final KafkaFutureImpl<Collection<ClientMetricsResourceListing>> result = new KafkaFutureImpl<>();
48+
future.whenComplete((listings, throwable) -> {
49+
if (throwable != null) {
50+
result.completeExceptionally(throwable);
51+
} else {
52+
result.complete(listings);
53+
}
54+
});
55+
return result;
56+
}
57+
}

clients/src/main/java/org/apache/kafka/common/protocol/ApiKeys.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ public enum ApiKeys {
116116
CONTROLLER_REGISTRATION(ApiMessageType.CONTROLLER_REGISTRATION),
117117
GET_TELEMETRY_SUBSCRIPTIONS(ApiMessageType.GET_TELEMETRY_SUBSCRIPTIONS),
118118
PUSH_TELEMETRY(ApiMessageType.PUSH_TELEMETRY),
119-
ASSIGN_REPLICAS_TO_DIRS(ApiMessageType.ASSIGN_REPLICAS_TO_DIRS);
119+
ASSIGN_REPLICAS_TO_DIRS(ApiMessageType.ASSIGN_REPLICAS_TO_DIRS),
120+
LIST_CLIENT_METRICS_RESOURCES(ApiMessageType.LIST_CLIENT_METRICS_RESOURCES);
120121

121122
private static final Map<ApiMessageType.ListenerType, EnumSet<ApiKeys>> APIS_BY_LISTENER =
122123
new EnumMap<>(ApiMessageType.ListenerType.class);

clients/src/main/java/org/apache/kafka/common/requests/AbstractRequest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ private static AbstractRequest doParseRequest(ApiKeys apiKey, short apiVersion,
322322
return PushTelemetryRequest.parse(buffer, apiVersion);
323323
case ASSIGN_REPLICAS_TO_DIRS:
324324
return AssignReplicasToDirsRequest.parse(buffer, apiVersion);
325+
case LIST_CLIENT_METRICS_RESOURCES:
326+
return ListClientMetricsResourcesRequest.parse(buffer, apiVersion);
325327
default:
326328
throw new AssertionError(String.format("ApiKey %s is not currently handled in `parseRequest`, the " +
327329
"code should be updated to do so.", apiKey));

clients/src/main/java/org/apache/kafka/common/requests/AbstractResponse.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ public static AbstractResponse parseResponse(ApiKeys apiKey, ByteBuffer response
259259
return PushTelemetryResponse.parse(responseBuffer, version);
260260
case ASSIGN_REPLICAS_TO_DIRS:
261261
return AssignReplicasToDirsResponse.parse(responseBuffer, version);
262+
case LIST_CLIENT_METRICS_RESOURCES:
263+
return ListClientMetricsResourcesResponse.parse(responseBuffer, version);
262264
default:
263265
throw new AssertionError(String.format("ApiKey %s is not currently handled in `parseResponse`, the " +
264266
"code should be updated to do so.", apiKey));
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.kafka.common.requests;
18+
19+
import org.apache.kafka.common.message.ListClientMetricsResourcesRequestData;
20+
import org.apache.kafka.common.message.ListClientMetricsResourcesResponseData;
21+
import org.apache.kafka.common.protocol.ApiKeys;
22+
import org.apache.kafka.common.protocol.ByteBufferAccessor;
23+
import org.apache.kafka.common.protocol.Errors;
24+
25+
import java.nio.ByteBuffer;
26+
27+
public class ListClientMetricsResourcesRequest extends AbstractRequest {
28+
public static class Builder extends AbstractRequest.Builder<ListClientMetricsResourcesRequest> {
29+
public final ListClientMetricsResourcesRequestData data;
30+
31+
public Builder(ListClientMetricsResourcesRequestData data) {
32+
super(ApiKeys.LIST_CLIENT_METRICS_RESOURCES);
33+
this.data = data;
34+
}
35+
36+
@Override
37+
public ListClientMetricsResourcesRequest build(short version) {
38+
return new ListClientMetricsResourcesRequest(data, version);
39+
}
40+
41+
@Override
42+
public String toString() {
43+
return data.toString();
44+
}
45+
}
46+
47+
private final ListClientMetricsResourcesRequestData data;
48+
49+
private ListClientMetricsResourcesRequest(ListClientMetricsResourcesRequestData data, short version) {
50+
super(ApiKeys.LIST_CLIENT_METRICS_RESOURCES, version);
51+
this.data = data;
52+
}
53+
54+
public ListClientMetricsResourcesRequestData data() {
55+
return data;
56+
}
57+
58+
@Override
59+
public ListClientMetricsResourcesResponse getErrorResponse(int throttleTimeMs, Throwable e) {
60+
Errors error = Errors.forException(e);
61+
ListClientMetricsResourcesResponseData response = new ListClientMetricsResourcesResponseData()
62+
.setErrorCode(error.code())
63+
.setThrottleTimeMs(throttleTimeMs);
64+
return new ListClientMetricsResourcesResponse(response);
65+
}
66+
67+
public static ListClientMetricsResourcesRequest parse(ByteBuffer buffer, short version) {
68+
return new ListClientMetricsResourcesRequest(new ListClientMetricsResourcesRequestData(
69+
new ByteBufferAccessor(buffer), version), version);
70+
}
71+
72+
@Override
73+
public String toString(boolean verbose) {
74+
return data.toString();
75+
}
76+
77+
}

0 commit comments

Comments
 (0)