Updated to support load balanced API Rest

- system collects all the domains, servers, and stats. /domains
- added support for a WSS state, displays on the UI
- moved all server related domain structures to ServerDomain* etc. to avoid collision with Domains
- create new Domains structure to handle Domains, Domain, Servers and Traffic at each level.
- updated initial lastUpate to the connection time rather than 0 which gave a silly duration.
- added properties for DomainTrack (Requests and Responses)
This commit is contained in:
Henry Camacho 2017-03-25 20:33:09 -05:00
parent 41adbfaef5
commit a72bbc63e4
8 changed files with 159 additions and 90 deletions

View File

@ -27,8 +27,9 @@
<th width="10%">Address</th> <th width="10%">Address</th>
<th width="10%">Xfer (in/out)</th> <th width="10%">Xfer (in/out)</th>
<th width="10%">Req/Resp</th> <th width="10%">Req/Resp</th>
<th width="10%">Time</th> <th width="5%">Duration</th>
<th width="10%">Idle</th> <th width="5%">State</th>
<th width="5%">Idle</th>
<th width="1%"><center><span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span></center></th> <th width="1%"><center><span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span></center></th>
@ -64,6 +65,7 @@
</td> </td>
<td>{{ s.duration | hfcduration }}</td> <td>{{ s.duration | hfcduration }}</td>
<td>{{ s.server_state }}</td>
<td>{{ s.idle | hfcduration }}</td> <td>{{ s.idle | hfcduration }}</td>
<td> <td>
<span class="glyphicon glyphicon-zoom-in" title="Detail" aria-hidden="false" ng-click="triggerDetail(s.server_id)"></span> <span class="glyphicon glyphicon-zoom-in" title="Detail" aria-hidden="false" ng-click="triggerDetail(s.server_id)"></span>

View File

@ -1,60 +1,69 @@
package genericlistener package genericlistener
//DomainsAPI -- Structure to support the server API //DomainsAPI -- A collections of all the domains
type DomainsAPI struct { //List of Domains -> DomainAPI
DomainName string `json:"domain_name"` //DomainsAPI -> DomainServerAPI
ServerID int64 `json:"server_id"` //
BytesIn int64 `json:"bytes_in"`
BytesOut int64 `json:"bytes_out"` //DomainServerAPI -- Container for Server Stats related to a domain
Requests int64 `json:"requests"` type DomainServerAPI struct {
Responses int64 `json:"responses"` ServerName string `json:"server_name"`
Traffic TrafficAPI `json:"traffic"`
} }
//NewDomainsAPI - Constructor //NewDomainServerAPI -- Constructor
func NewDomainsAPI(c *Connection, d *DomainTrack) (s *DomainsAPI) { func NewDomainServerAPI(domain string, conn *Connection) (p *DomainServerAPI) {
s = new(DomainsAPI) p = new(DomainServerAPI)
s.DomainName = d.DomainName dt := conn.DomainTrack[domain]
s.ServerID = c.ConnectionID() p.Traffic.BytesIn = dt.BytesIn()
s.BytesIn = d.BytesIn() p.Traffic.BytesOut = dt.BytesOut()
s.BytesOut = d.BytesOut() p.Traffic.Requests = dt.Requests()
s.Requests = d.requests p.Traffic.Responses = dt.Responses()
s.Responses = d.responses p.ServerName = conn.ServerName()
return return
} }
//DomainsAPIContainer -- Holder for all the Servers //DomainAPI -- Container for domain and related servers
type DomainsAPIContainer struct {
Domains []*DomainsAPI `json:"domains"`
}
//NewDomainsAPIContainer -- Constructor
func NewDomainsAPIContainer() (p *DomainsAPIContainer) {
p = new(DomainsAPIContainer)
p.Domains = make([]*DomainsAPI, 0)
return p
}
//DomainAPI -- Structure to support the server API
type DomainAPI struct { type DomainAPI struct {
DomainName string `json:"domain_name"` TotalServers int `json:"server_total"`
ServerID int64 `json:"server_id"` Servers []*DomainServerAPI `json:"servers"`
BytesIn int64 `json:"bytes_in"` Traffic TrafficAPI `json:"traffic"`
BytesOut int64 `json:"bytes_out"`
Requests int64 `json:"requests"`
Responses int64 `json:"responses"`
Source string `json:"source_addr"`
} }
//NewDomainAPI - Constructor //NewDomainAPI -- Constructor
func NewDomainAPI(c *Connection, d *DomainTrack) (s *DomainAPI) { func NewDomainAPI(domain string, domainLoadBalance *DomainLoadBalance) (p *DomainAPI) {
s = new(DomainAPI) p = new(DomainAPI)
s.DomainName = d.DomainName for pos := range domainLoadBalance.connections {
s.ServerID = c.ConnectionID() ds := NewDomainServerAPI(domain, domainLoadBalance.connections[pos])
s.BytesIn = d.BytesIn() p.Servers = append(p.Servers, ds)
s.BytesOut = d.BytesOut() p.TotalServers++
s.Requests = d.requests p.Traffic.BytesIn += domainLoadBalance.connections[pos].BytesIn()
s.Responses = d.responses p.Traffic.BytesOut += domainLoadBalance.connections[pos].BytesOut()
s.Source = c.Source() p.Traffic.Requests += domainLoadBalance.connections[pos].requests
p.Traffic.Responses += domainLoadBalance.connections[pos].responses
}
return
}
//DomainsAPI -- Container for Domains
type DomainsAPI struct {
TotalDomains int `json:"domain_total"`
Domains []*DomainAPI `json:"domains"`
Traffic TrafficAPI `json:"traffic"`
}
//NewDomainsAPI -- Constructor
func NewDomainsAPI(domains map[string]*DomainLoadBalance) (p *DomainsAPI) {
p = new(DomainsAPI)
for domain := range domains {
d := NewDomainAPI(domain, domains[domain])
p.Domains = append(p.Domains, d)
p.Traffic.BytesIn += d.Traffic.BytesIn
p.Traffic.BytesOut += d.Traffic.BytesOut
p.Traffic.Requests += d.Traffic.Requests
p.Traffic.Responses += d.Traffic.Responses
}
return return
} }

View File

@ -6,12 +6,13 @@ import "time"
type ServerAPI struct { type ServerAPI struct {
ServerName string `json:"server_name"` ServerName string `json:"server_name"`
ServerID int64 `json:"server_id"` ServerID int64 `json:"server_id"`
Domains []*DomainAPI `json:"domains"` Domains []*ServerDomainAPI `json:"domains"`
Duration float64 `json:"duration"` Duration float64 `json:"duration"`
Idle float64 `json:"idle"` Idle float64 `json:"idle"`
BytesIn int64 `json:"bytes_in"` BytesIn int64 `json:"bytes_in"`
BytesOut int64 `json:"bytes_out"` BytesOut int64 `json:"bytes_out"`
Source string `json:"source_address"` Source string `json:"source_address"`
State bool `json:"server_state"`
} }
//NewServerAPI - Constructor //NewServerAPI - Constructor
@ -19,7 +20,7 @@ func NewServerAPI(c *Connection) (s *ServerAPI) {
s = new(ServerAPI) s = new(ServerAPI)
s.ServerName = c.ServerName() s.ServerName = c.ServerName()
s.ServerID = c.ConnectionID() s.ServerID = c.ConnectionID()
s.Domains = make([]*DomainAPI, 0) s.Domains = make([]*ServerDomainAPI, 0)
s.Duration = time.Since(c.ConnectTime()).Seconds() s.Duration = time.Since(c.ConnectTime()).Seconds()
s.Idle = time.Since(c.LastUpdate()).Seconds() s.Idle = time.Since(c.LastUpdate()).Seconds()
s.BytesIn = c.BytesIn() s.BytesIn = c.BytesIn()
@ -28,7 +29,7 @@ func NewServerAPI(c *Connection) (s *ServerAPI) {
for domainName := range c.DomainTrack { for domainName := range c.DomainTrack {
domainAPI := NewDomainAPI(c, c.DomainTrack[domainName]) domainAPI := NewServerDomainAPI(c, c.DomainTrack[domainName])
s.Domains = append(s.Domains, domainAPI) s.Domains = append(s.Domains, domainAPI)
} }
return return

View File

@ -0,0 +1,60 @@
package genericlistener
//ServerDomainsAPI -- Structure to support the server API
type ServerDomainsAPI struct {
DomainName string `json:"domain_name"`
ServerID int64 `json:"server_id"`
BytesIn int64 `json:"bytes_in"`
BytesOut int64 `json:"bytes_out"`
Requests int64 `json:"requests"`
Responses int64 `json:"responses"`
}
//NewServerDomainsAPI - Constructor
func NewServerDomainsAPI(c *Connection, d *DomainTrack) (s *ServerDomainsAPI) {
s = new(ServerDomainsAPI)
s.DomainName = d.DomainName
s.ServerID = c.ConnectionID()
s.BytesIn = d.BytesIn()
s.BytesOut = d.BytesOut()
s.Requests = d.requests
s.Responses = d.responses
return
}
//ServerDomainsAPIContainer -- Holder for all the Servers
type ServerDomainsAPIContainer struct {
Domains []*ServerDomainsAPI `json:"domains"`
}
//NewServerDomainsAPIContainer -- Constructor
func NewServerDomainsAPIContainer() (p *ServerDomainsAPIContainer) {
p = new(ServerDomainsAPIContainer)
p.Domains = make([]*ServerDomainsAPI, 0)
return p
}
//ServerDomainAPI -- Structure to support the server API
type ServerDomainAPI struct {
DomainName string `json:"domain_name"`
ServerID int64 `json:"server_id"`
BytesIn int64 `json:"bytes_in"`
BytesOut int64 `json:"bytes_out"`
Requests int64 `json:"requests"`
Responses int64 `json:"responses"`
Source string `json:"source_addr"`
}
//NewServerDomainAPI - Constructor
func NewServerDomainAPI(c *Connection, d *DomainTrack) (s *ServerDomainAPI) {
s = new(ServerDomainAPI)
s.DomainName = d.DomainName
s.ServerID = c.ConnectionID()
s.BytesIn = d.BytesIn()
s.BytesOut = d.BytesOut()
s.Requests = d.requests
s.Responses = d.responses
s.Source = c.Source()
return
}

View File

@ -6,7 +6,7 @@ import "time"
type ServersAPI struct { type ServersAPI struct {
ServerName string `json:"server_name"` ServerName string `json:"server_name"`
ServerID int64 `json:"server_id"` ServerID int64 `json:"server_id"`
Domains []*DomainAPI `json:"domains"` Domains []*ServerDomainAPI `json:"domains"`
Duration float64 `json:"duration"` Duration float64 `json:"duration"`
Idle float64 `json:"idle"` Idle float64 `json:"idle"`
BytesIn int64 `json:"bytes_in"` BytesIn int64 `json:"bytes_in"`
@ -14,6 +14,7 @@ type ServersAPI struct {
Requests int64 `json:"requests"` Requests int64 `json:"requests"`
Responses int64 `json:"responses"` Responses int64 `json:"responses"`
Source string `json:"source_address"` Source string `json:"source_address"`
State bool `json:"server_state"`
} }
//NewServersAPI - Constructor //NewServersAPI - Constructor
@ -21,7 +22,7 @@ func NewServersAPI(c *Connection) (s *ServersAPI) {
s = new(ServersAPI) s = new(ServersAPI)
s.ServerName = c.ServerName() s.ServerName = c.ServerName()
s.ServerID = c.ConnectionID() s.ServerID = c.ConnectionID()
s.Domains = make([]*DomainAPI, 0) s.Domains = make([]*ServerDomainAPI, 0)
s.Duration = time.Since(c.ConnectTime()).Seconds() s.Duration = time.Since(c.ConnectTime()).Seconds()
s.Idle = time.Since(c.LastUpdate()).Seconds() s.Idle = time.Since(c.LastUpdate()).Seconds()
s.BytesIn = c.BytesIn() s.BytesIn = c.BytesIn()
@ -29,10 +30,11 @@ func NewServersAPI(c *Connection) (s *ServersAPI) {
s.Requests = c.requests s.Requests = c.requests
s.Responses = c.responses s.Responses = c.responses
s.Source = c.Source() s.Source = c.Source()
s.State = c.State()
for d := range c.DomainTrack { for d := range c.DomainTrack {
dt := c.DomainTrack[d] dt := c.DomainTrack[d]
domainAPI := NewDomainAPI(c, dt) domainAPI := NewServerDomainAPI(c, dt)
s.Domains = append(s.Domains, domainAPI) s.Domains = append(s.Domains, domainAPI)
} }
return return

View File

@ -98,18 +98,7 @@ func getDomainsEndpoint(w http.ResponseWriter, r *http.Request) {
serverStatus.AdminStats.IncRequests() serverStatus.AdminStats.IncRequests()
domainsContainer := NewDomainsAPIContainer() domainsContainer := NewDomainsAPI(connectionTable.domains)
for domain := range connectionTable.domains {
domainLB := connectionTable.domains[domain]
conns := domainLB.Connections()
for pos := range conns {
conn := conns[pos]
domainAPI := NewDomainsAPI(conn, conn.DomainTrack[domain])
domainsContainer.Domains = append(domainsContainer.Domains, domainAPI)
}
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
@ -139,11 +128,11 @@ func getDomainEndpoint(w http.ResponseWriter, r *http.Request) {
env.ErrorURI = r.RequestURI env.ErrorURI = r.RequestURI
env.ErrorDescription = "domain-name not found" env.ErrorDescription = "domain-name not found"
} else { } else {
var domainAPIContainer []*DomainAPI var domainAPIContainer []*ServerDomainAPI
conns := domainLB.Connections() conns := domainLB.Connections()
for pos := range conns { for pos := range conns {
conn := conns[pos] conn := conns[pos]
domainAPI := NewDomainAPI(conn, conn.DomainTrack[domainName]) domainAPI := NewServerDomainAPI(conn, conn.DomainTrack[domainName])
domainAPIContainer = append(domainAPIContainer, domainAPI) domainAPIContainer = append(domainAPIContainer, domainAPI)
} }
env.Result = domainAPIContainer env.Result = domainAPIContainer

View File

@ -12,11 +12,6 @@ import (
"git.daplie.com/Daplie/go-rvpn-server/rvpn/packer" "git.daplie.com/Daplie/go-rvpn-server/rvpn/packer"
) )
var upgrader = websocket.Upgrader{
ReadBufferSize: 4096,
WriteBufferSize: 4096,
}
// Connection track websocket and faciliates in and out data // Connection track websocket and faciliates in and out data
type Connection struct { type Connection struct {
mutex sync.Mutex mutex sync.Mutex
@ -91,6 +86,7 @@ func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress s
p.initialDomains = initialDomains p.initialDomains = initialDomains
p.connectionTrack = connectionTrack p.connectionTrack = connectionTrack
p.DomainTrack = make(map[string]*DomainTrack) p.DomainTrack = make(map[string]*DomainTrack)
p.lastUpdate = time.Now()
for _, domain := range initialDomains { for _, domain := range initialDomains {
p.AddTrackedDomain(string(domain.(string))) p.AddTrackedDomain(string(domain.(string)))

View File

@ -49,3 +49,13 @@ func (c *DomainTrack) AddRequests() {
func (c *DomainTrack) AddResponses() { func (c *DomainTrack) AddResponses() {
c.responses = c.responses + 1 c.responses = c.responses + 1
} }
//Requests -- Property
func (c *DomainTrack) Requests() int64 {
return c.requests
}
//Responses -- Property
func (c *DomainTrack) Responses() int64 {
return c.responses
}