Skip to content

Commit e2c27a7

Browse files
committed
Support to get kyuubi server event with RESTful api
1 parent 3b205a3 commit e2c27a7

File tree

7 files changed

+206
-2
lines changed

7 files changed

+206
-2
lines changed

kyuubi-rest-client/src/main/java/org/apache/kyuubi/client/AdminRestApi.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.*;
2121
import org.apache.commons.lang3.StringUtils;
2222
import org.apache.kyuubi.client.api.v1.dto.Engine;
23+
import org.apache.kyuubi.client.api.v1.dto.KyuubiServerEvent;
2324
import org.apache.kyuubi.client.api.v1.dto.OperationData;
2425
import org.apache.kyuubi.client.api.v1.dto.ServerData;
2526
import org.apache.kyuubi.client.api.v1.dto.SessionData;
@@ -165,6 +166,12 @@ public List<ServerData> listServers() {
165166
return Arrays.asList(result);
166167
}
167168

169+
public KyuubiServerEvent getServerEvent() {
170+
return this.getClient()
171+
.get(
172+
API_BASE_PATH + "/server/event", null, KyuubiServerEvent.class, client.getAuthHeader());
173+
}
174+
168175
private IRestClient getClient() {
169176
return this.client.getHttpClient();
170177
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
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.kyuubi.client.api.v1.dto;
19+
20+
import java.util.Collections;
21+
import java.util.Map;
22+
import java.util.Objects;
23+
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
24+
import org.apache.commons.lang3.builder.ToStringStyle;
25+
26+
public class KyuubiServerEvent {
27+
private String serverName;
28+
private Long startTime;
29+
private Long eventTime;
30+
private String state;
31+
private String serverIp;
32+
private Map<String, String> serverConf;
33+
private Map<String, String> serverEnv;
34+
35+
public KyuubiServerEvent() {}
36+
37+
public KyuubiServerEvent(
38+
String serverName,
39+
Long startTime,
40+
Long eventTime,
41+
String state,
42+
String serverIp,
43+
Map<String, String> serverConf,
44+
Map<String, String> serverEnv) {
45+
this.serverName = serverName;
46+
this.startTime = startTime;
47+
this.eventTime = eventTime;
48+
this.state = state;
49+
this.serverIp = serverIp;
50+
this.serverConf = serverConf;
51+
this.serverEnv = serverEnv;
52+
}
53+
54+
public String getServerName() {
55+
return serverName;
56+
}
57+
58+
public void setServerName(String serverName) {
59+
this.serverName = serverName;
60+
}
61+
62+
public Long getStartTime() {
63+
return startTime;
64+
}
65+
66+
public void setStartTime(Long startTime) {
67+
this.startTime = startTime;
68+
}
69+
70+
public Long getEventTime() {
71+
return eventTime;
72+
}
73+
74+
public void setEventTime(Long eventTime) {
75+
this.eventTime = eventTime;
76+
}
77+
78+
public String getState() {
79+
return state;
80+
}
81+
82+
public void setState(String state) {
83+
this.state = state;
84+
}
85+
86+
public String getServerIp() {
87+
return serverIp;
88+
}
89+
90+
public void setServerIp(String serverIp) {
91+
this.serverIp = serverIp;
92+
}
93+
94+
public Map<String, String> getServerConf() {
95+
if (null == serverConf) {
96+
return Collections.emptyMap();
97+
}
98+
return serverConf;
99+
}
100+
101+
public void setServerConf(Map<String, String> serverConf) {
102+
this.serverConf = serverConf;
103+
}
104+
105+
public Map<String, String> getServerEnv() {
106+
if (null == serverEnv) {
107+
return Collections.emptyMap();
108+
}
109+
return serverEnv;
110+
}
111+
112+
public void setServerEnv(Map<String, String> serverEnv) {
113+
this.serverEnv = serverEnv;
114+
}
115+
116+
@Override
117+
public boolean equals(Object o) {
118+
if (this == o) return true;
119+
if (o == null || getClass() != o.getClass()) return false;
120+
KyuubiServerEvent that = (KyuubiServerEvent) o;
121+
return Objects.equals(getServerName(), that.getServerName())
122+
&& Objects.equals(getStartTime(), that.getStartTime())
123+
&& Objects.equals(getEventTime(), that.getEventTime())
124+
&& Objects.equals(getState(), that.getState())
125+
&& Objects.equals(getServerIp(), that.getServerIp())
126+
&& Objects.equals(getServerConf(), that.getServerConf())
127+
&& Objects.equals(getServerEnv(), that.getServerEnv());
128+
}
129+
130+
@Override
131+
public int hashCode() {
132+
return Objects.hash(
133+
getServerName(),
134+
getStartTime(),
135+
getEventTime(),
136+
getState(),
137+
getServerIp(),
138+
getServerConf(),
139+
getServerEnv());
140+
}
141+
142+
@Override
143+
public String toString() {
144+
return ReflectionToStringBuilder.toString(this, ToStringStyle.JSON_STYLE);
145+
}
146+
}

kyuubi-server/src/main/scala/org/apache/kyuubi/server/KyuubiServer.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ class KyuubiServer(name: String) extends Serverable(name) {
231231
super.stop()
232232
}
233233

234+
def getServerEvent(): Option[KyuubiServerInfoEvent] = {
235+
KyuubiServerInfoEvent(this, state)
236+
}
237+
234238
private def initLoggerEventHandler(conf: KyuubiConf): Unit = {
235239
ServerEventHandlerRegister.registerEventLoggers(conf)
236240
}

kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/ApiUtils.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import scala.collection.JavaConverters._
2121

2222
import org.apache.kyuubi.{Logging, Utils}
2323
import org.apache.kyuubi.client.api.v1.dto
24-
import org.apache.kyuubi.client.api.v1.dto.{OperationData, OperationProgress, ServerData, SessionData}
24+
import org.apache.kyuubi.client.api.v1.dto.{KyuubiServerEvent, OperationData, OperationProgress, ServerData, SessionData}
25+
import org.apache.kyuubi.events.KyuubiServerInfoEvent
2526
import org.apache.kyuubi.ha.client.ServiceNodeInfo
2627
import org.apache.kyuubi.operation.KyuubiOperation
2728
import org.apache.kyuubi.session.KyuubiSession
@@ -136,6 +137,18 @@ object ApiUtils extends Logging {
136137
"Running")
137138
}
138139

140+
def serverEvent(serverEvent: KyuubiServerInfoEvent): KyuubiServerEvent = {
141+
if (serverEvent == null) return new KyuubiServerEvent()
142+
new KyuubiServerEvent(
143+
serverEvent.serverName,
144+
serverEvent.startTime,
145+
serverEvent.eventTime,
146+
serverEvent.state,
147+
serverEvent.serverIP,
148+
serverEvent.serverConf.asJava,
149+
serverEvent.serverEnv.asJava)
150+
}
151+
139152
def logAndRefineErrorMsg(errorMsg: String, throwable: Throwable): String = {
140153
error(errorMsg, throwable)
141154
s"$errorMsg: ${Utils.prettyPrint(throwable)}"

kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/AdminResource.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ private[v1] class AdminResource extends ApiRequestContext with Logging {
378378
new Content(
379379
mediaType = MediaType.APPLICATION_JSON,
380380
array = new ArraySchema(schema = new Schema(implementation =
381-
classOf[OperationData])))),
381+
classOf[ServerData])))),
382382
description = "list all live kyuubi servers")
383383
@GET
384384
@Path("server")
@@ -401,6 +401,19 @@ private[v1] class AdminResource extends ApiRequestContext with Logging {
401401
servers.toSeq
402402
}
403403

404+
@ApiResponse(
405+
responseCode = "200",
406+
content = Array(
407+
new Content(
408+
mediaType = MediaType.APPLICATION_JSON,
409+
schema = new Schema(implementation = classOf[KyuubiServerEvent]))),
410+
description = "Get the server event")
411+
@GET
412+
@Path("server/event")
413+
def getServerEvent(): KyuubiServerEvent = {
414+
ApiUtils.serverEvent(KyuubiServer.kyuubiServer.getServerEvent().orNull)
415+
}
416+
404417
private def normalizeEngineInfo(
405418
userName: String,
406419
engineType: String,

kyuubi-server/src/test/scala/org/apache/kyuubi/server/api/v1/AdminResourceSuite.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,4 +841,15 @@ class AdminResourceSuite extends KyuubiFunSuite with RestFrontendTestHelper {
841841
assert("Running".equals(testServer.getStatus))
842842
}
843843
}
844+
845+
test("get server event") {
846+
val response = webTarget.path("api/v1/admin/server/event")
847+
.request()
848+
.header(AUTHORIZATION_HEADER, HttpAuthUtils.basicAuthorizationHeader(Utils.currentUser))
849+
.get
850+
851+
assert(response.getStatus === 200)
852+
val serverEvent = response.readEntity(classOf[KyuubiServerEvent])
853+
assert(serverEvent.getStartTime > 0)
854+
}
844855
}

kyuubi-server/src/test/scala/org/apache/kyuubi/server/rest/client/AdminRestApiSuite.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,14 @@ class AdminRestApiSuite extends RestClientTestHelper {
173173
assert(servers.map(s => s.getInstance()).contains(server.frontendServices.last.connectionUrl))
174174
}
175175
}
176+
177+
test("get server event") {
178+
val spnegoKyuubiRestClient: KyuubiRestClient =
179+
KyuubiRestClient.builder(baseUri.toString)
180+
.authHeaderMethod(KyuubiRestClient.AuthHeaderMethod.SPNEGO)
181+
.spnegoHost("localhost")
182+
.build()
183+
val adminRestApi = new AdminRestApi(spnegoKyuubiRestClient)
184+
assert(adminRestApi.getServerEvent.getStartTime > 0)
185+
}
176186
}

0 commit comments

Comments
 (0)