[KYUUBI #3156] Expose REST frontend connection metrics

### _Why are the changes needed?_

### _How was this patch tested?_
- [ ] Add some test cases that check the changes thoroughly including negative and positive cases if possible

- [ ] Add screenshots for manual tests if appropriate

- [ ] [Run test](https://kyuubi.apache.org/docs/latest/develop_tools/testing.html#running-tests) locally before make a pull request

Closes #3233 from lightning-L/kyuubi-3156.

Closes #3156

7e297de7 [Tianlin Liao] [KYUUBI #3156] Expose REST frontend connection metrics

Authored-by: Tianlin Liao <tiliao@ebay.com>
Signed-off-by: Fei Wang <fwang12@ebay.com>
This commit is contained in:
Tianlin Liao 2022-08-18 17:08:14 +08:00 committed by Fei Wang
parent 05e4e8f8c1
commit 7d238896fc
5 changed files with 70 additions and 0 deletions

View File

@ -33,6 +33,7 @@ object MetricsConstants {
final private val CONN = KYUUBI + "connection."
final private val THRIFT_HTTP_CONN = KYUUBI + "thrift.http.connection."
final private val THRIFT_BINARY_CONN = KYUUBI + "thrift.binary.connection."
final private val REST_CONN = KYUUBI + "rest.connection."
final val CONN_OPEN: String = CONN + "opened"
final val CONN_FAIL: String = CONN + "failed"
@ -46,6 +47,10 @@ object MetricsConstants {
final val THRIFT_BINARY_CONN_FAIL: String = THRIFT_BINARY_CONN + "failed"
final val THRIFT_BINARY_CONN_TOTAL: String = THRIFT_BINARY_CONN + "total"
final val REST_CONN_OPEN: String = REST_CONN + "opened"
final val REST_CONN_FAIL: String = REST_CONN + "failed"
final val REST_CONN_TOTAL: String = REST_CONN + "total"
final private val ENGINE = KYUUBI + "engine."
final val ENGINE_FAIL: String = ENGINE + "failed"
final val ENGINE_TIMEOUT: String = ENGINE + "timeout"

View File

@ -26,6 +26,8 @@ import org.eclipse.jetty.server.handler.HandlerWrapper
import org.apache.kyuubi.config.KyuubiConf
import org.apache.kyuubi.config.KyuubiConf.{AUTHENTICATION_METHOD, ENGINE_SECURITY_ENABLED}
import org.apache.kyuubi.metrics.MetricsConstants.{REST_CONN_FAIL, REST_CONN_OPEN, REST_CONN_TOTAL}
import org.apache.kyuubi.metrics.MetricsSystem
import org.apache.kyuubi.service.authentication.{AuthTypes, InternalSecurityAccessor}
import org.apache.kyuubi.service.authentication.AuthTypes.KERBEROS
@ -51,6 +53,10 @@ class KyuubiHttpAuthenticationFactory(conf: KyuubiConf) {
baseRequest: Request,
request: HttpServletRequest,
response: HttpServletResponse): Unit = {
MetricsSystem.tracing { ms =>
ms.incCount(REST_CONN_TOTAL)
ms.incCount(REST_CONN_OPEN)
}
try {
if (kerberosEnabled) {
ugi.doAs(new PrivilegedAction[Unit] {
@ -62,6 +68,15 @@ class KyuubiHttpAuthenticationFactory(conf: KyuubiConf) {
handler.handle(target, baseRequest, request, response)
}
} finally {
val statusCode = response.getStatus
if (statusCode < 200 || statusCode >= 300) {
MetricsSystem.tracing { ms =>
ms.incCount(REST_CONN_FAIL)
}
}
MetricsSystem.tracing { ms =>
ms.decCount(REST_CONN_OPEN)
}
AuthenticationFilter.HTTP_CLIENT_USER_NAME.remove()
AuthenticationFilter.HTTP_CLIENT_IP_ADDRESS.remove()
}

View File

@ -23,13 +23,23 @@ import javax.ws.rs.core.{MediaType, Response}
import scala.collection.JavaConverters._
import org.scalatest.time.SpanSugar.convertIntToGrainOfTime
import org.apache.kyuubi.{KyuubiFunSuite, RestFrontendTestHelper}
import org.apache.kyuubi.client.api.v1.dto._
import org.apache.kyuubi.events.KyuubiSessionEvent
import org.apache.kyuubi.metrics.{MetricsConstants, MetricsSystem}
import org.apache.kyuubi.operation.OperationHandle
class SessionsResourceSuite extends KyuubiFunSuite with RestFrontendTestHelper {
override protected def beforeEach(): Unit = {
super.beforeEach()
eventually(timeout(10.seconds), interval(200.milliseconds)) {
assert(MetricsSystem.counterValue(MetricsConstants.REST_CONN_OPEN).getOrElse(0L) === 0)
}
}
test("open/close and count session") {
val requestObj = new SessionOpenRequest(
1,
@ -127,6 +137,11 @@ class SessionsResourceSuite extends KyuubiFunSuite with RestFrontendTestHelper {
}
test("get infoType") {
val totalConnections =
MetricsSystem.counterValue(MetricsConstants.REST_CONN_TOTAL).getOrElse(0L)
val failedConnections =
MetricsSystem.counterValue(MetricsConstants.REST_CONN_FAIL).getOrElse(0L)
val requestObj = new SessionOpenRequest(
1,
"admin",
@ -160,6 +175,14 @@ class SessionsResourceSuite extends KyuubiFunSuite with RestFrontendTestHelper {
response = webTarget.path(s"api/v1/sessions/$sessionHandle/info/str")
.request().get()
assert(404 == response.getStatus)
eventually(timeout(3.seconds), interval(200.milliseconds)) {
assert(MetricsSystem.counterValue(
MetricsConstants.REST_CONN_TOTAL).getOrElse(0L) - totalConnections === 6)
assert(MetricsSystem.counterValue(MetricsConstants.REST_CONN_OPEN).getOrElse(0L) === 0)
assert(MetricsSystem.counterValue(
MetricsConstants.REST_CONN_FAIL).getOrElse(0L) - failedConnections === 4)
}
}
test("submit operation and get operation handle") {

View File

@ -23,9 +23,11 @@ import java.nio.file.{Files, Paths}
import org.apache.hadoop.security.UserGroupInformation
import org.apache.hive.service.rpc.thrift.TProtocolVersion
import org.scalatest.time.SpanSugar.convertIntToGrainOfTime
import org.apache.kyuubi.{BatchTestHelper, RestClientTestHelper, Utils}
import org.apache.kyuubi.ctl.TestPrematureExit
import org.apache.kyuubi.metrics.{MetricsConstants, MetricsSystem}
import org.apache.kyuubi.session.KyuubiSessionManager
class BatchCliSuite extends RestClientTestHelper with TestPrematureExit with BatchTestHelper {
@ -74,6 +76,9 @@ class BatchCliSuite extends RestClientTestHelper with TestPrematureExit with Bat
}
test("basic batch rest client") {
val totalConnections =
MetricsSystem.counterValue(MetricsConstants.REST_CONN_TOTAL).getOrElse(0L)
val createArgs = Array(
"create",
"batch",
@ -121,6 +126,12 @@ class BatchCliSuite extends RestClientTestHelper with TestPrematureExit with Bat
"--password",
ldapUserPasswd)
result = testPrematureExitForControlCli(deleteArgs, "\"success\":true")
eventually(timeout(3.seconds), interval(200.milliseconds)) {
assert(MetricsSystem.counterValue(
MetricsConstants.REST_CONN_TOTAL).getOrElse(0L) - totalConnections === 5)
assert(MetricsSystem.counterValue(MetricsConstants.REST_CONN_OPEN).getOrElse(0L) === 0)
}
}
test("spnego batch rest client") {

View File

@ -19,10 +19,13 @@ package org.apache.kyuubi.server.rest.client
import java.util.Base64
import org.scalatest.time.SpanSugar.convertIntToGrainOfTime
import org.apache.kyuubi.{BatchTestHelper, RestClientTestHelper}
import org.apache.kyuubi.client.{BatchRestApi, KyuubiRestClient}
import org.apache.kyuubi.client.api.v1.dto.Batch
import org.apache.kyuubi.client.exception.KyuubiRestException
import org.apache.kyuubi.metrics.{MetricsConstants, MetricsSystem}
class BatchRestApiSuite extends RestClientTestHelper with BatchTestHelper {
@ -59,6 +62,11 @@ class BatchRestApiSuite extends RestClientTestHelper with BatchTestHelper {
}
test("basic batch rest client with invalid user") {
val totalConnections =
MetricsSystem.counterValue(MetricsConstants.REST_CONN_TOTAL).getOrElse(0L)
val failedConnections =
MetricsSystem.counterValue(MetricsConstants.REST_CONN_FAIL).getOrElse(0L)
val basicKyuubiRestClient: KyuubiRestClient =
KyuubiRestClient.builder(baseUri.toString)
.authHeaderMethod(KyuubiRestClient.AuthHeaderMethod.BASIC)
@ -75,6 +83,14 @@ class BatchRestApiSuite extends RestClientTestHelper with BatchTestHelper {
assert(e.getCause.toString.contains(s"Error validating LDAP user: uid=${customUser}"))
basicKyuubiRestClient.close()
eventually(timeout(3.seconds), interval(200.milliseconds)) {
assert(MetricsSystem.counterValue(
MetricsConstants.REST_CONN_TOTAL).getOrElse(0L) - totalConnections === 1)
assert(MetricsSystem.counterValue(MetricsConstants.REST_CONN_OPEN).getOrElse(0L) === 0)
assert(MetricsSystem.counterValue(
MetricsConstants.REST_CONN_FAIL).getOrElse(0L) - failedConnections === 1)
}
}
test("spnego batch rest client") {