From 5646427d183cc7d1793fb08966fbd6969cc07580 Mon Sep 17 00:00:00 2001 From: Ivan Krutov Date: Thu, 5 Oct 2017 12:04:23 +0300 Subject: [PATCH] Added ability to show overall number of requests in /ping (fixes #121) --- docs/multiple-instances.adoc | 4 ++-- proxy.go | 26 ++++++++++++++++++-------- proxy_test.go | 4 +++- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/docs/multiple-instances.adoc b/docs/multiple-instances.adoc index 6a0f4cf..0eb1214 100644 --- a/docs/multiple-instances.adoc +++ b/docs/multiple-instances.adoc @@ -10,10 +10,10 @@ $ curl -s http://example.com:4444/ping .Result [source,javascript] ---- -{"uptime":"2m46.854829503s","lastReloadTime":"2017-05-12 12:33:06.322038542 +0300 MSK"} +{"uptime":"2m46.854829503s","lastReloadTime":"2017-05-12 12:33:06.322038542 +0300 MSK","numRequests":42} ---- -It returns `200 OK` when Ggr operates normally. Additionally server uptime and last quota reload time are returned in JSON format. +It returns `200 OK` when Ggr operates normally. Additionally server uptime, last quota reload time and overall number of session requests from service startup are returned in JSON format. === Why Ggr is Stateless Selenium uses an HTTP-based protocol. That means every action in Selenium, e.g. launching browser or taking screenshot is a separate HTTP request. When multiple instances of Ggr are handling requests behind load balancer every request can be routed to any of these instances. Here's how it works. diff --git a/proxy.go b/proxy.go index df35378..e05cbd8 100644 --- a/proxy.go +++ b/proxy.go @@ -53,7 +53,7 @@ var ( quota = make(map[string]Browsers) routes Routes = make(Routes) num uint64 - numLock sync.Mutex + numLock sync.RWMutex confLock sync.RWMutex ) @@ -150,6 +150,12 @@ func serial() uint64 { return id } +func getSerial() uint64 { + numLock.RLock() + defer numLock.RUnlock() + return num +} + func info(r *http.Request) (user, remote string) { if guestAccessAllowed { user = guestUserName @@ -335,7 +341,8 @@ func ping(w http.ResponseWriter, _ *http.Request) { json.NewEncoder(w).Encode(struct { Uptime string `json:"uptime"` LastReloadTime string `json:"lastReloadTime"` - }{time.Since(startTime).String(), lastReloadTime.String()}) + NumRequests uint64 `json:"numRequests"` + }{time.Since(startTime).String(), lastReloadTime.String(), getSerial()}) } func err(w http.ResponseWriter, _ *http.Request) { @@ -493,12 +500,15 @@ func vnc(wsconn *websocket.Conn) { path = vncInfo.Path } switch scheme { - case vncScheme: proxyVNC(wsconn, sessionId, host, port) - case wsScheme: proxyWebSockets(wsconn, sessionId, host, port, path) - default: { - log.Printf("[UNSUPPORTED_HOST_VNC_SCHEME] [%s]\n", scheme) - return - } + case vncScheme: + proxyVNC(wsconn, sessionId, host, port) + case wsScheme: + proxyWebSockets(wsconn, sessionId, host, port, path) + default: + { + log.Printf("[UNSUPPORTED_HOST_VNC_SCHEME] [%s]\n", scheme) + return + } } } else { log.Printf("[UNKNOWN_VNC_HOST] [%s]\n", sum) diff --git a/proxy_test.go b/proxy_test.go index 6ef0264..cd994a4 100644 --- a/proxy_test.go +++ b/proxy_test.go @@ -87,7 +87,7 @@ func TestPing(t *testing.T) { AssertThat(t, rsp, Code{http.StatusOK}) AssertThat(t, rsp.Body, Is{Not{nil}}) - var data map[string]string + var data map[string]interface{} bt, readErr := ioutil.ReadAll(rsp.Body) AssertThat(t, readErr, Is{nil}) jsonErr := json.Unmarshal(bt, &data) @@ -96,6 +96,8 @@ func TestPing(t *testing.T) { AssertThat(t, hasUptime, Is{true}) _, hasLastReloadTime := data["lastReloadTime"] AssertThat(t, hasLastReloadTime, Is{true}) + _, hasNumRequests := data["numRequests"] + AssertThat(t, hasNumRequests, Is{true}) } func TestErr(t *testing.T) {