Skip to content

Commit

Permalink
adding GSDK metrics (#470)
Browse files Browse the repository at this point in the history
Co-authored-by: Dimitris Gkanatsios <dgkanatsios@digkanatdesktop>
  • Loading branch information
dgkanatsios and Dimitris Gkanatsios authored Nov 26, 2024
1 parent 6453367 commit 39a5bb3
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 38 deletions.
14 changes: 7 additions & 7 deletions cmd/e2e/gameserverapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net"
"net/http"
"time"
Expand Down Expand Up @@ -87,7 +87,7 @@ var _ = Describe("GameServerAPI tests", func() {
g.Expect(r.StatusCode).To(Equal(http.StatusOK))
defer r.Body.Close()
var l mpsv1alpha1.GameServerBuildList
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
g.Expect(err).ToNot(HaveOccurred())
err = json.Unmarshal(body, &l)
g.Expect(err).ToNot(HaveOccurred())
Expand All @@ -108,7 +108,7 @@ var _ = Describe("GameServerAPI tests", func() {
defer r.Body.Close()
g.Expect(r.StatusCode).To(Equal(http.StatusOK))
var bu mpsv1alpha1.GameServerBuild
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
g.Expect(err).ToNot(HaveOccurred())
err = json.Unmarshal(body, &bu)
g.Expect(err).ToNot(HaveOccurred())
Expand All @@ -121,7 +121,7 @@ var _ = Describe("GameServerAPI tests", func() {
r, err := client.Get(fmt.Sprintf("%s/gameserverbuilds/%s/%s/gameservers", url, testNamespace, buildName))
g.Expect(err).ToNot(HaveOccurred())
defer r.Body.Close()
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
g.Expect(err).ToNot(HaveOccurred())
err = json.Unmarshal(body, &gsList)
g.Expect(err).ToNot(HaveOccurred())
Expand All @@ -135,7 +135,7 @@ var _ = Describe("GameServerAPI tests", func() {
g.Expect(err).ToNot(HaveOccurred())
defer r.Body.Close()
var gs mpsv1alpha1.GameServer
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
g.Expect(err).ToNot(HaveOccurred())
err = json.Unmarshal(body, &gs)
g.Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -166,7 +166,7 @@ var _ = Describe("GameServerAPI tests", func() {
Expect(err).ToNot(HaveOccurred())
defer r.Body.Close()
var gsList mpsv1alpha1.GameServerList
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
Expect(err).ToNot(HaveOccurred())
err = json.Unmarshal(body, &gsList)
Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -196,7 +196,7 @@ var _ = Describe("GameServerAPI tests", func() {
g.Expect(err).ToNot(HaveOccurred())
defer r.Body.Close()
g.Expect(r.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
g.Expect(err).ToNot(HaveOccurred())
var bu mpsv1alpha1.GameServerBuild
err = json.Unmarshal(body, &bu)
Expand Down
3 changes: 1 addition & 2 deletions cmd/e2e/utilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"math/rand"
"net/http"
"strings"
Expand Down Expand Up @@ -287,7 +286,7 @@ func allocate(buildID, sessionID string, cert tls.Certificate) error {
return fmt.Errorf("%s %d", invalidStatusCode, resp.StatusCode)
}
//Read the response body
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
Expand Down
16 changes: 8 additions & 8 deletions cmd/gameserverapi/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
Expand Down Expand Up @@ -53,7 +53,7 @@ var _ = Describe("GameServer API service tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
var l mpsv1alpha1.GameServerBuildList
err = json.Unmarshal(body, &l)
Expand All @@ -77,7 +77,7 @@ var _ = Describe("GameServer API service tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
var b mpsv1alpha1.GameServerBuild
err = json.Unmarshal(body, &b)
Expand Down Expand Up @@ -134,7 +134,7 @@ var _ = Describe("GameServer API service tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
var b mpsv1alpha1.GameServerBuild
err = json.Unmarshal(body, &b)
Expand All @@ -149,7 +149,7 @@ var _ = Describe("GameServer API service tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
var l mpsv1alpha1.GameServerList
err = json.Unmarshal(body, &l)
Expand All @@ -174,7 +174,7 @@ var _ = Describe("GameServer API service tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
var g mpsv1alpha1.GameServer
err = json.Unmarshal(body, &g)
Expand All @@ -189,7 +189,7 @@ var _ = Describe("GameServer API service tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
var l mpsv1alpha1.GameServerDetailList
err = json.Unmarshal(body, &l)
Expand All @@ -214,7 +214,7 @@ var _ = Describe("GameServer API service tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
var g mpsv1alpha1.GameServerDetail
err = json.Unmarshal(body, &g)
Expand Down
4 changes: 2 additions & 2 deletions cmd/initcontainer/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"log"
"os"
"testing"
Expand Down Expand Up @@ -50,7 +50,7 @@ func (suite *initContainerTestSuite) TestInitContainer() {
jsonFile, err := os.Open(testGsdkConfigFile)
assert.NoError(suite.T(), err)
defer jsonFile.Close()
byteValue, err := ioutil.ReadAll(jsonFile)
byteValue, err := io.ReadAll(jsonFile)
assert.NoError(suite.T(), err)
var gsdkConfig *GsdkConfig
err = json.Unmarshal(byteValue, &gsdkConfig)
Expand Down
1 change: 1 addition & 0 deletions cmd/nodeagent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func main() {
n := NewNodeAgentManager(dynamicClient, nodeName, logEveryHeartbeat, ignoreHealthFromHeartbeat, time.Now, true)
log.Debug("Starting HTTP server")
http.HandleFunc("/v1/sessionHosts/", n.heartbeatHandler)
http.HandleFunc("/v1/metrics/", n.metricsHandler)
http.HandleFunc("/healthz", healthzHandler)
http.Handle("/metrics", promhttp.Handler())

Expand Down
24 changes: 24 additions & 0 deletions cmd/nodeagent/nodeagentmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,30 @@ func (n *NodeAgentManager) gameServerDeleted(objUnstructured interface{}) {
n.gameServerMap.Delete(gameServerName)
}

// we want to log the GSDK version/flavor once, this variable is used to track that
// it's OK if we log it multiple times, but we want to avoid spamming the logs
var gsdkMetricsLogged = false

// this endpoint is used to receive GSDK info from the gameserver
// v1/metrics/{sessionHostId}/gsdkinfo
func (n *NodeAgentManager) metricsHandler(w http.ResponseWriter, r *http.Request) {
re := regexp.MustCompile(`.*/v1/metrics\/(.*?)(/gsdkinfo|$)`)
match := re.FindStringSubmatch(r.RequestURI)
gameServerName := match[1]
var gi GsdkVersionInfo
err := json.NewDecoder(r.Body).Decode(&gi)
if err != nil {
badRequest(w, err, "cannot deserialize json")
return
}
if !gsdkMetricsLogged {
log.Infof("GSDK metrics received from gameserver %s, GSDK flavor and version: %s-%s", gameServerName, gi.Flavor, gi.Version)
gsdkMetricsLogged = true
}

w.WriteHeader(http.StatusOK)
}

// heartbeatHandler is the http handler handling heartbeats from the GameServer Pods running on this Node
// it responds by sending instructions/signal for the next operation
// on Thundernetes, the only operation that NodeAgent can signal to the GameServer is that the GameServer has been allocated (its state has transitioned to Active)
Expand Down
38 changes: 27 additions & 11 deletions cmd/nodeagent/nodeagentmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"math/rand"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -46,7 +46,7 @@ var _ = Describe("nodeagent tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusBadRequest))
_, err := ioutil.ReadAll(res.Body)
_, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
})
It("heartbeat with empty fields should return error", func() {
Expand All @@ -59,7 +59,7 @@ var _ = Describe("nodeagent tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusBadRequest))
_, err := ioutil.ReadAll(res.Body)
_, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
})
It("heartbeat with body should work", func() {
Expand Down Expand Up @@ -90,7 +90,7 @@ var _ = Describe("nodeagent tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
resBody, err := ioutil.ReadAll(res.Body)
resBody, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
hbr := HeartbeatResponse{}
_ = json.Unmarshal(resBody, &hbr)
Expand Down Expand Up @@ -149,7 +149,7 @@ var _ = Describe("nodeagent tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
resBody, err := ioutil.ReadAll(res.Body)
resBody, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
hbr := HeartbeatResponse{}
_ = json.Unmarshal(resBody, &hbr)
Expand All @@ -167,7 +167,7 @@ var _ = Describe("nodeagent tests", func() {
res = w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
resBody, err = ioutil.ReadAll(res.Body)
resBody, err = io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
hbr = HeartbeatResponse{}
err = json.Unmarshal(resBody, &hbr)
Expand Down Expand Up @@ -204,7 +204,7 @@ var _ = Describe("nodeagent tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
resBody, err := ioutil.ReadAll(res.Body)
resBody, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
hbr := HeartbeatResponse{}
_ = json.Unmarshal(resBody, &hbr)
Expand Down Expand Up @@ -400,7 +400,7 @@ var _ = Describe("nodeagent tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
resBody, err := ioutil.ReadAll(res.Body)
resBody, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
hbr := HeartbeatResponse{}
_ = json.Unmarshal(resBody, &hbr)
Expand Down Expand Up @@ -435,7 +435,7 @@ var _ = Describe("nodeagent tests", func() {
res = w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
resBody, err = ioutil.ReadAll(res.Body)
resBody, err = io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
hbr = HeartbeatResponse{}
err = json.Unmarshal(resBody, &hbr)
Expand Down Expand Up @@ -519,7 +519,7 @@ var _ = Describe("nodeagent tests", func() {
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
resBody, err := ioutil.ReadAll(res.Body)
resBody, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
hbr := HeartbeatResponse{}
_ = json.Unmarshal(resBody, &hbr)
Expand All @@ -537,7 +537,7 @@ var _ = Describe("nodeagent tests", func() {
res = w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
resBody, err = ioutil.ReadAll(res.Body)
resBody, err = io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
hbr = HeartbeatResponse{}
err = json.Unmarshal(resBody, &hbr)
Expand Down Expand Up @@ -836,6 +836,22 @@ var _ = Describe("nodeagent tests", func() {
g.Expect(gameServerHealth).To(Equal("Healthy"))
}, "3s").Should(Succeed())
})
It("GSDK metrics should work", func() {
gi := &GsdkVersionInfo{
Version: "1.0.0",
Flavor: "CustomGameEngine",
}
b, _ := json.Marshal(gi)
req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/v1/metrics/%s/gsdkinfo", testGameServerName), bytes.NewReader(b))
w := httptest.NewRecorder()
dynamicClient := newDynamicInterface()

n := NewNodeAgentManager(dynamicClient, testNodeName, false, false, time.Now, true)
n.metricsHandler(w, req)
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusOK))
})
})

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
Expand Down
8 changes: 8 additions & 0 deletions cmd/nodeagent/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ var (
)
)

// GsdkVersionInfo contains details about the GSDK version of the game server
type GsdkVersionInfo struct {
// Flavor is the engine of GSDK (Unreal/Unity/C++ etc.)
Flavor string `json:"Flavor"`
// Version is the version of GSDK
Version string `json:"Version"`
}

// HeartbeatRequest contains data for the heartbeat request coming from the GSDK running alongside GameServer
type HeartbeatRequest struct {
// CurrentGameState is the current state of the game server
Expand Down
Loading

0 comments on commit 39a5bb3

Please sign in to comment.