Skip to content

Commit

Permalink
support status api
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Leung <rleungx@gmail.com>
  • Loading branch information
rleungx committed Dec 21, 2023
1 parent cfbc9b9 commit 576856d
Show file tree
Hide file tree
Showing 12 changed files with 125 additions and 22 deletions.
1 change: 1 addition & 0 deletions pkg/mcs/resourcemanager/server/apis/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func NewService(srv *rmserver.Service) *Service {
c.Next()
})
apiHandlerEngine.GET("metrics", utils.PromHandler())
apiHandlerEngine.GET("status", utils.StatusHandler)
pprof.Register(apiHandlerEngine)
endpoint := apiHandlerEngine.Group(APIPathPrefix)
endpoint.Use(multiservicesapi.ServiceRedirector())
Expand Down
1 change: 1 addition & 0 deletions pkg/mcs/scheduling/server/apis/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func NewService(srv *scheserver.Service) *Service {
c.Next()
})
apiHandlerEngine.GET("metrics", mcsutils.PromHandler())
apiHandlerEngine.GET("status", mcsutils.StatusHandler)
pprof.Register(apiHandlerEngine)
root := apiHandlerEngine.Group(APIPathPrefix)
root.Use(multiservicesapi.ServiceRedirector())
Expand Down
5 changes: 5 additions & 0 deletions pkg/mcs/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,8 @@ func (bs *BaseServer) GetListener() net.Listener {
func (bs *BaseServer) IsSecure() bool {
return bs.secure
}

// StartTimestamp returns the start timestamp of this server
func (bs *BaseServer) StartTimestamp() int64 {
return bs.startTimestamp
}
1 change: 1 addition & 0 deletions pkg/mcs/tso/server/apis/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func NewService(srv *tsoserver.Service) *Service {
c.Next()
})
apiHandlerEngine.GET("metrics", utils.PromHandler())
apiHandlerEngine.GET("status", utils.StatusHandler)
pprof.Register(apiHandlerEngine)
root := apiHandlerEngine.Group(APIPathPrefix)
root.Use(multiservicesapi.ServiceRedirector())
Expand Down
16 changes: 16 additions & 0 deletions pkg/mcs/utils/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ import (
"github.com/soheilhy/cmux"
"github.com/tikv/pd/pkg/errs"
"github.com/tikv/pd/pkg/utils/apiutil"
"github.com/tikv/pd/pkg/utils/apiutil/multiservicesapi"
"github.com/tikv/pd/pkg/utils/etcdutil"
"github.com/tikv/pd/pkg/utils/grpcutil"
"github.com/tikv/pd/pkg/utils/logutil"
"github.com/tikv/pd/pkg/versioninfo"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/pkg/types"
"go.uber.org/zap"
Expand Down Expand Up @@ -78,6 +80,19 @@ func PromHandler() gin.HandlerFunc {
}
}

// StatusHandler is a handler to get status info.
func StatusHandler(c *gin.Context) {
svr := c.MustGet(multiservicesapi.ServiceContextKey).(server)
version := versioninfo.Status{
BuildTS: versioninfo.PDBuildTS,
GitHash: versioninfo.PDGitHash,
Version: versioninfo.PDReleaseVersion,
StartTimestamp: svr.StartTimestamp(),
}

c.IndentedJSON(http.StatusOK, version)
}

type server interface {
GetBackendEndpoints() string
Context() context.Context
Expand All @@ -97,6 +112,7 @@ type server interface {
RegisterGRPCService(*grpc.Server)
SetUpRestHandler() (http.Handler, apiutil.APIServiceGroup)
diagnosticspb.DiagnosticsServer
StartTimestamp() int64
}

// WaitAPIServiceReady waits for the api service ready.
Expand Down
8 changes: 8 additions & 0 deletions pkg/versioninfo/versioninfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ import (
"go.uber.org/zap"
)

// NOTE: This type is exported by HTTP API. Please pay more attention when modifying it.
type Status struct {
BuildTS string `json:"build_ts"`
Version string `json:"version"`
GitHash string `json:"git_hash"`
StartTimestamp int64 `json:"start_timestamp"`
}

const (
// CommunityEdition is the default edition for building.
CommunityEdition = "Community"
Expand Down
10 changes: 1 addition & 9 deletions server/api/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ type statusHandler struct {
rd *render.Render
}

// NOTE: This type is exported by HTTP API. Please pay more attention when modifying it.
type status struct {
BuildTS string `json:"build_ts"`
Version string `json:"version"`
GitHash string `json:"git_hash"`
StartTimestamp int64 `json:"start_timestamp"`
}

func newStatusHandler(svr *server.Server, rd *render.Render) *statusHandler {
return &statusHandler{
svr: svr,
Expand All @@ -47,7 +39,7 @@ func newStatusHandler(svr *server.Server, rd *render.Render) *statusHandler {
// @Success 200 {object} status
// @Router /status [get]
func (h *statusHandler) GetPDStatus(w http.ResponseWriter, r *http.Request) {
version := status{
version := versioninfo.Status{
BuildTS: versioninfo.PDBuildTS,
GitHash: versioninfo.PDGitHash,
Version: versioninfo.PDReleaseVersion,
Expand Down
2 changes: 1 addition & 1 deletion server/api/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

func checkStatusResponse(re *require.Assertions, body []byte) {
got := status{}
got := versioninfo.Status{}
re.NoError(json.Unmarshal(body, &got))
re.Equal(versioninfo.PDBuildTS, got.BuildTS)
re.Equal(versioninfo.PDGitHash, got.GitHash)
Expand Down
16 changes: 16 additions & 0 deletions tests/integrations/mcs/resourcemanager/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/tikv/pd/client/grpcutil"
"github.com/tikv/pd/pkg/utils/tempurl"
"github.com/tikv/pd/pkg/versioninfo"
"github.com/tikv/pd/tests"
)

Expand Down Expand Up @@ -102,4 +103,19 @@ func TestResourceManagerServer(t *testing.T) {
re.NoError(err)
re.Contains(string(respBytes), "resource_manager_server_info")
}

// Test status handler
{
resp, err := http.Get(addr + "/status")
re.NoError(err)
defer resp.Body.Close()
re.Equal(http.StatusOK, resp.StatusCode)
respBytes, err := io.ReadAll(resp.Body)
re.NoError(err)
var s versioninfo.Status
re.NoError(json.Unmarshal(respBytes, &s))
re.Equal(versioninfo.PDBuildTS, s.BuildTS)
re.Equal(versioninfo.PDGitHash, s.GitHash)
re.Equal(versioninfo.PDReleaseVersion, s.Version)
}
}
44 changes: 44 additions & 0 deletions tests/integrations/mcs/scheduling/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"testing"
"time"
Expand All @@ -22,6 +23,7 @@ import (
"github.com/tikv/pd/pkg/storage"
"github.com/tikv/pd/pkg/utils/apiutil"
"github.com/tikv/pd/pkg/utils/testutil"
"github.com/tikv/pd/pkg/versioninfo"
"github.com/tikv/pd/tests"
)

Expand Down Expand Up @@ -545,3 +547,45 @@ func (suite *apiTestSuite) checkFollowerForward(cluster *tests.TestCluster) {
)
re.NoError(err)
}

func (suite *apiTestSuite) TestMetrics() {
suite.env.RunTestInAPIMode(suite.checkMetrics)
}

func (suite *apiTestSuite) checkMetrics(cluster *tests.TestCluster) {
re := suite.Require()
s := cluster.GetSchedulingPrimaryServer()
testutil.Eventually(re, func() bool {
return s.IsServing()
}, testutil.WithWaitFor(5*time.Second), testutil.WithTickInterval(50*time.Millisecond))
resp, err := http.Get(s.GetConfig().GetAdvertiseListenAddr() + "/metrics")
re.NoError(err)
defer resp.Body.Close()
re.Equal(http.StatusOK, resp.StatusCode)
respBytes, err := io.ReadAll(resp.Body)
re.NoError(err)
re.Contains(string(respBytes), "scheduling_server_info")
}

func (suite *apiTestSuite) TestStatus() {
suite.env.RunTestInAPIMode(suite.checkStatus)
}

func (suite *apiTestSuite) checkStatus(cluster *tests.TestCluster) {
re := suite.Require()
s := cluster.GetSchedulingPrimaryServer()
testutil.Eventually(re, func() bool {
return s.IsServing()
}, testutil.WithWaitFor(5*time.Second), testutil.WithTickInterval(50*time.Millisecond))
resp, err := http.Get(s.GetConfig().GetAdvertiseListenAddr() + "/status")
re.NoError(err)
defer resp.Body.Close()
re.Equal(http.StatusOK, resp.StatusCode)
respBytes, err := io.ReadAll(resp.Body)
re.NoError(err)
var status versioninfo.Status
re.NoError(json.Unmarshal(respBytes, &status))
re.Equal(versioninfo.PDBuildTS, status.BuildTS)
re.Equal(versioninfo.PDGitHash, status.GitHash)
re.Equal(versioninfo.PDReleaseVersion, status.Version)
}
31 changes: 31 additions & 0 deletions tests/integrations/mcs/tso/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/tikv/pd/pkg/storage/endpoint"
"github.com/tikv/pd/pkg/utils/apiutil"
"github.com/tikv/pd/pkg/utils/testutil"
"github.com/tikv/pd/pkg/versioninfo"
"github.com/tikv/pd/server/config"
"github.com/tikv/pd/tests"
)
Expand Down Expand Up @@ -244,3 +245,33 @@ func TestForwardOnlyTSONoScheduling(t *testing.T) {
testutil.Status(re, http.StatusInternalServerError), testutil.StringContain(re, "[PD:apiutil:ErrRedirect]redirect failed"))
re.NoError(err)
}

func (suite *tsoAPITestSuite) TestMetrics() {
re := suite.Require()

primary := suite.tsoCluster.WaitForDefaultPrimaryServing(re)
resp, err := http.Get(primary.GetConfig().GetAdvertiseListenAddr() + "/metrics")
re.NoError(err)
defer resp.Body.Close()
re.Equal(http.StatusOK, resp.StatusCode)
respBytes, err := io.ReadAll(resp.Body)
re.NoError(err)
re.Contains(string(respBytes), "tso_server_info")
}

func (suite *tsoAPITestSuite) TestStatus() {
re := suite.Require()

primary := suite.tsoCluster.WaitForDefaultPrimaryServing(re)
resp, err := http.Get(primary.GetConfig().GetAdvertiseListenAddr() + "/status")
re.NoError(err)
defer resp.Body.Close()
re.Equal(http.StatusOK, resp.StatusCode)
respBytes, err := io.ReadAll(resp.Body)
re.NoError(err)
var s versioninfo.Status
re.NoError(json.Unmarshal(respBytes, &s))
re.Equal(versioninfo.PDBuildTS, s.BuildTS)
re.Equal(versioninfo.PDGitHash, s.GitHash)
re.Equal(versioninfo.PDReleaseVersion, s.Version)
}
12 changes: 0 additions & 12 deletions tests/integrations/mcs/tso/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -571,18 +571,6 @@ func (suite *CommonTestSuite) TestAdvertiseAddr() {
re.Equal(conf.GetListenAddr(), conf.GetAdvertiseListenAddr())
}

func (suite *CommonTestSuite) TestMetrics() {
re := suite.Require()

resp, err := http.Get(suite.tsoDefaultPrimaryServer.GetConfig().GetAdvertiseListenAddr() + "/metrics")
re.NoError(err)
defer resp.Body.Close()
re.Equal(http.StatusOK, resp.StatusCode)
respBytes, err := io.ReadAll(resp.Body)
re.NoError(err)
re.Contains(string(respBytes), "tso_server_info")
}

func (suite *CommonTestSuite) TestBootstrapDefaultKeyspaceGroup() {
re := suite.Require()

Expand Down

0 comments on commit 576856d

Please sign in to comment.