Several Considerations for Load Balancing, Collection of Bulk ServerStatus

- added a number of global status collections
- this requires wedging into things..
- removing direct address to come functions putting them though serverStatus
This commit is contained in:
Henry Camacho 2017-03-19 19:04:47 -05:00
parent 057ec00f82
commit ba67cebb29
20 changed files with 399 additions and 38 deletions

View File

@ -1,4 +1,5 @@
rvpn:
serverName: rvpn1
wssdomain: localhost.daplie.me
admindomain: rvpn.daplie.invalid
genericlistener: 9999
@ -14,6 +15,6 @@ rvpn:
test3.daplie.me:
secret: abc123
loadbalancing:
defaultmethod: 'round-robin'
defaultmethod: round-robin

View File

@ -28,6 +28,7 @@
</div>
<nav class="collapse navbar-collapse" id="bs-navbar">
<ul class="nav navbar-nav">
<li> <a href="/admin/status">Status</a> </li>
<li> <a href="/admin/servers">Servers</a> </li>
<li> <a href="/admin/#domains">Domains</a> </li>
<li> <a href="/admin/#connections">Connections</a> </li>

View File

@ -4,15 +4,23 @@ var app = angular.module("rvpnApp", ["ngRoute", "angular-duration-format"]);
app.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("/admin/status/", {
templateUrl : "admin/partials/status.html"
})
.when("/admin/index.html", {
templateUrl : "admin/partials/servers.html"
})
.when("/admin/servers/", {
templateUrl : "admin/partials/servers.html"
})
.when("/admin/#domains", {
templateUrl : "green.htm"
})
.when("/blue", {
templateUrl : "blue.htm"
});
@ -81,7 +89,7 @@ app.controller('serverController', function ($scope, $http) {
}
$scope.triggerDetail = function(id) {
console.log("triggerDetail ", id, $scope.servers_trigger_details[id])
//console.log("triggerDetail ", id, $scope.servers_trigger_details[id])
if ($scope.servers_trigger_details[id] == true) {
$scope.servers_trigger_details[id] = false;
} else {
@ -90,7 +98,7 @@ app.controller('serverController', function ($scope, $http) {
};
$scope.checkDetail = function(id) {
console.log("checkDetail ", id, $scope.servers_trigger_details[id])
//console.log("checkDetail ", id, $scope.servers_trigger_details[id])
if ($scope.servers_trigger_details[id] == true) {
return false;
} else {

View File

@ -26,6 +26,7 @@
<th width="10%">Name</th>
<th width="10%">Address</th>
<th width="10%">Xfer (in/out)</th>
<th width="10%">Req/Resp</th>
<th width="10%">Time</th>
<th width="10%">Idle</th>
<th width="1%"><center><span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span></center></th>
@ -46,16 +47,34 @@
<td>
{{ s.bytes_in | bytes }}/{{ s.bytes_out | bytes }}
<div ng-hide="checkDetail(s.server_id)">
domains({{ s.domains.length}})
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.bytes_in | bytes }}/{{ d.bytes_out | bytes }}
</div>
</div>
</td>
<td>
{{ s.requests }}/{{ s.responses }}
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.requests }}/{{ d.responses }}
</div>
</div>
</td>
<td>{{ s.duration | hfcduration }}</td>
<td>{{ s.idle | hfcduration }}</td>
<td>
<span class="glyphicon glyphicon-zoom-in" title="Detail" aria-hidden="false" ng-click="triggerDetail(s.server_id)"></span>
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
<span class="glyphicon glyphicon-zoom-in" title="Detail" aria-hidden="false" ng-click="triggerDetail(s.server_id+d.domain_name)"></span>
</div>
</div>
</td>
</tr>

View File

@ -0,0 +1,22 @@
<div class="panel panel-default" data-ng-controller="serverController">
<div class="panel-heading">
<div class="panel-title">
<div class="row">
<div class="col-md-6">
Status
</div>
<div class="col-md-6">
<form class="form-inline pull-right">
<div class="form-group">
<label for="search">Search:</label>
<input type="text" class="form-control" id="search" data-ng-model="servers_search">
</div>
<button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
<span class="glyphicon glyphicon-refresh" title="Refresh" aria-hidden="false" ng-click="updateView()"></span>
</button>
</form>
</div>
</div>
</div>
</div>
</div>

24
main.go
View File

@ -33,6 +33,7 @@ var (
dwell int
cancelcheck int
lbDefaultMethod string
serverName string
)
func init() {
@ -48,7 +49,7 @@ func main() {
viper.AddConfigPath("./")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
panic(fmt.Errorf("fatal error config file: %s", err))
}
flag.IntVar(&argDeadTime, "dead-time-counter", 5, "deadtime counter in seconds")
@ -61,6 +62,7 @@ func main() {
dwell = deadtime.(map[string]interface{})["dwell"].(int)
cancelcheck = deadtime.(map[string]interface{})["cancelcheck"].(int)
lbDefaultMethod = viper.Get("rvpn.loadbalancing.defaultmethod").(string)
serverName = viper.Get("rvpn.serverName").(string)
loginfo.Println("startup")
@ -78,6 +80,14 @@ func main() {
ctx, cancelContext := context.WithCancel(context.Background())
defer cancelContext()
serverStatus := genericlistener.NewStatus(ctx)
serverStatus.AdminDomain = adminHostName
serverStatus.WssDomain = wssHostName
serverStatus.Name = serverName
serverStatus.StartTime = time.Now()
serverStatus.DeadTime = genericlistener.NewStatusDeadTime(dwell, idle, cancelcheck)
serverStatus.LoadbalanceDefaultMethod = lbDefaultMethod
// Setup for GenericListenServe.
// - establish context for the generic listener
// - startup listener
@ -88,17 +98,17 @@ func main() {
// - match protocol
connectionTracking := genericlistener.NewTracking()
serverStatus.ConnectionTracking = connectionTracking
go connectionTracking.Run(ctx)
connectionTable = genericlistener.NewTable(dwell, idle)
serverStatus.ConnectionTable = connectionTable
go connectionTable.Run(ctx)
genericListeners := genericlistener.NewGenerListeners(ctx, connectionTable, connectionTracking, secretKey, certbundle, wssHostName,
adminHostName, cancelcheck, lbDefaultMethod)
genericListeners := genericlistener.NewGenerListeners(ctx, secretKey, certbundle, serverStatus)
serverStatus.GenericListeners = genericListeners
genericListeners.Run(ctx, argGenericBinding)
go genericListeners.Run(ctx, argGenericBinding)
//Run for 10 minutes and then shutdown cleanly
time.Sleep(6000 * time.Second)
cancelContext()
select {}
}

View File

@ -6,6 +6,8 @@ type DomainsAPI struct {
ServerID int64 `json:"server_id"`
BytesIn int64 `json:"bytes_in"`
BytesOut int64 `json:"bytes_out"`
Requests int64 `json:"requests"`
Responses int64 `json:"responses"`
}
//NewDomainsAPI - Constructor
@ -15,6 +17,8 @@ func NewDomainsAPI(c *Connection, d *DomainTrack) (s *DomainsAPI) {
s.ServerID = c.ConnectionID()
s.BytesIn = d.BytesIn()
s.BytesOut = d.BytesOut()
s.Requests = d.requests
s.Responses = d.responses
return
}
@ -37,16 +41,20 @@ type DomainAPI struct {
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"`
}
//NewDomainsAPI - Constructor
//NewDomainAPI - Constructor
func NewDomainAPI(c *Connection, d *DomainTrack) (s *DomainAPI) {
s = new(DomainAPI)
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

@ -14,6 +14,8 @@ type ServersAPI struct {
Idle float64 `json:"idle"`
BytesIn int64 `json:"bytes_in"`
BytesOut int64 `json:"bytes_out"`
Requests int64 `json:"requests"`
Responses int64 `json:"responses"`
Source string `json:"source_address"`
}
@ -27,6 +29,8 @@ func NewServersAPI(c *Connection) (s *ServersAPI) {
s.Idle = time.Since(c.LastUpdate()).Seconds()
s.BytesIn = c.BytesIn()
s.BytesOut = c.BytesOut()
s.Requests = c.requests
s.Responses = c.responses
s.Source = c.Source()
for d := range c.DomainTrack {

View File

@ -0,0 +1,32 @@
package genericlistener
import "time"
//StatusAPI -- Structure to support the server API
type StatusAPI struct {
Name string `json:"name"`
Uptime float64 `json:"uptime"`
WssDomain string `json:"wss_domain"`
AdminDomain string `json:"admin_domain"`
LoadbalanceDefaultMethod string `json:"loadbalance_default_method"`
DeadTime *StatusDeadTimeAPI `json:"dead_time"`
AdminStats *TrafficAPI `json:"admin_traffic"`
TrafficStats *TrafficAPI `json:"traffic"`
ExtConnections *ConnectionStats
WSSConnections *ConnectionStats
}
//NewStatusAPI - Constructor
func NewStatusAPI(c *Status) (s *StatusAPI) {
s = new(StatusAPI)
s.Name = c.Name
s.Uptime = time.Since(c.StartTime).Seconds()
s.WssDomain = c.WssDomain
s.AdminDomain = c.AdminDomain
s.LoadbalanceDefaultMethod = c.LoadbalanceDefaultMethod
s.DeadTime = NewStatusDeadTimeAPI(c.DeadTime.dwell, c.DeadTime.idle, c.DeadTime.cancelcheck)
s.AdminStats = NewTrafficAPI(c.AdminStats.Requests, c.AdminStats.Responses, c.AdminStats.BytesIn, c.AdminStats.BytesOut)
s.TrafficStats = NewTrafficAPI(c.TrafficStats.Requests, c.TrafficStats.Responses, c.TrafficStats.BytesIn, c.TrafficStats.BytesOut)
return
}

View File

@ -0,0 +1,17 @@
package genericlistener
//StatusDeadTimeAPI -- structure for deadtime configuration
type StatusDeadTimeAPI struct {
Dwell int `json:"dwell"`
Idle int `json:"idle"`
Cancelcheck int `json:"cancel_check"`
}
//NewStatusDeadTimeAPI -- constructor
func NewStatusDeadTimeAPI(dwell int, idle int, cancelcheck int) (p *StatusDeadTimeAPI) {
p = new(StatusDeadTimeAPI)
p.Dwell = dwell
p.Idle = idle
p.Cancelcheck = cancelcheck
return
}

View File

@ -0,0 +1,20 @@
package genericlistener
//TrafficStats --
type TrafficAPI struct {
Requests int64
Responses int64
BytesIn int64
BytesOut int64
}
//NewTrafficStats -- Consttuctor
func NewTrafficAPI(requests int64, responses int64, bytes_in int64, bytes_out int64) (p *TrafficAPI) {
p = new(TrafficAPI)
p.Requests = requests
p.Responses = responses
p.BytesIn = bytes_in
p.BytesOut = bytes_out
return
}

View File

@ -16,12 +16,16 @@ const (
)
var connectionTable *Table
var serverStatusAPI *Status
//handleAdminClient -
// - expecting an existing oneConnListener with a qualified wss client connected.
// - auth will happen again since we were just peeking at the token.
func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
connectionTable = ctx.Value(ctxConnectionTable).(*Table)
serverStatus := ctx.Value(ctxServerStatus).(*Status)
connectionTable = serverStatus.ConnectionTable
serverStatusAPI = serverStatus
router := mux.NewRouter().StrictSlash(true)
router.PathPrefix("/admin/").Handler(http.StripPrefix("/admin/", http.FileServer(http.Dir("html/admin"))))
@ -46,6 +50,7 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
router.HandleFunc(endPointPrefix+"servers", getServersEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"server/", getServerEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"server/{server-id}", getServerEndpoint).Methods("GET")
router.HandleFunc(endPointPrefix+"status/", getStatusEndpoint).Methods("GET")
s := &http.Server{
Addr: ":80",
@ -64,6 +69,20 @@ func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
}
}
func getStatusEndpoint(w http.ResponseWriter, r *http.Request) {
pc, _, _, _ := runtime.Caller(0)
loginfo.Println(runtime.FuncForPC(pc).Name())
statusContainer := NewStatusAPI(serverStatusAPI)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
env := envelope.NewEnvelope("domains/GET")
env.Result = statusContainer
env.GenerateWriter(w)
}
func getDomainsEndpoint(w http.ResponseWriter, r *http.Request) {
pc, _, _, _ := runtime.Caller(0)
loginfo.Println(runtime.FuncForPC(pc).Name())

View File

@ -50,6 +50,12 @@ type Connection struct {
// bytes out
bytesOut int64
// requests
requests int64
// response
responses int64
// Connect Time
connectTime time.Time
@ -79,6 +85,8 @@ func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress s
p.source = remoteAddress
p.bytesIn = 0
p.bytesOut = 0
p.requests = 0
p.responses = 0
p.send = make(chan *SendTrack)
p.connectTime = time.Now()
p.initialDomains = initialDomains
@ -143,6 +151,14 @@ func (c *Connection) addOut(num int64) {
c.bytesOut = c.bytesOut + num
}
func (c *Connection) addRequests() {
c.requests = c.requests + 1
}
func (c *Connection) addResponse() {
c.responses = c.responses + 1
}
//ConnectionTable -- property
func (c *Connection) ConnectionTable() (table *Table) {
table = c.connectionTable
@ -251,12 +267,14 @@ func (c *Connection) Reader(ctx context.Context) {
//Support for tracking outbound traffic based on domain.
if domainTrack, ok := c.DomainTrack[track.domain]; ok {
//if ok then add to structure, else warn there is something wrong
domainTrack.AddIn(int64(len(message)))
domainTrack.AddOut(int64(len(message)))
domainTrack.AddResponses()
}
track.conn.Write(p.Data.Data())
c.addIn(int64(len(message)))
c.addResponse()
loginfo.Println("end of read")
}
}
@ -290,11 +308,13 @@ func (c *Connection) Writer() {
messageLen := int64(len(message.data))
c.addOut(messageLen)
c.addRequests()
//Support for tracking outbound traffic based on domain.
if domainTrack, ok := c.DomainTrack[message.domain]; ok {
//if ok then add to structure, else warn there is something wrong
domainTrack.AddOut(messageLen)
domainTrack.AddIn(messageLen)
domainTrack.AddRequests()
loginfo.Println("adding ", messageLen, " to ", message.domain)
} else {
logdebug.Println("attempting to add bytes to ", message.domain, "it does not exist")

View File

@ -5,6 +5,8 @@ type DomainTrack struct {
DomainName string
bytesIn int64
bytesOut int64
requests int64
responses int64
}
//NewDomainTrack -- Constructor
@ -13,6 +15,8 @@ func NewDomainTrack(domainName string) (p *DomainTrack) {
p.DomainName = domainName
p.bytesIn = 0
p.bytesOut = 0
p.requests = 0
p.responses = 0
return
}
@ -28,7 +32,7 @@ func (c *DomainTrack) BytesOut() (b int64) {
return
}
//AddIn - Porperty
//AddIn - Property
func (c *DomainTrack) AddIn(num int64) {
c.bytesIn = c.bytesIn + num
}
@ -37,3 +41,13 @@ func (c *DomainTrack) AddIn(num int64) {
func (c *DomainTrack) AddOut(num int64) {
c.bytesOut = c.bytesOut + num
}
//AddRequests - Property
func (c *DomainTrack) AddRequests() {
c.requests = c.requests + 1
}
//AddResponses - Property
func (c *DomainTrack) AddResponses() {
c.responses = c.responses + 1
}

View File

@ -26,8 +26,11 @@ type contextKey string
//CtxConnectionTrack
const (
ctxSecretKey contextKey = "secretKey"
ctxConnectionTable contextKey = "connectionTable"
ctxSecretKey contextKey = "secretKey"
ctxServerStatus contextKey = "serverstatus"
//ctxConnectionTable contextKey = "connectionTable"
ctxConfig contextKey = "config"
ctxListenerRegistration contextKey = "listenerRegistration"
ctxConnectionTrack contextKey = "connectionTrack"
@ -271,16 +274,16 @@ func handleStream(ctx context.Context, wConn *WedgeConn) {
//handleExternalHTTPRequest -
// - get a wConn and start processing requests
func handleExternalHTTPRequest(ctx context.Context, extConn *WedgeConn, hostname string, service string) {
connectionTracking := ctx.Value(ctxConnectionTrack).(*Tracking)
//connectionTracking := ctx.Value(ctxConnectionTrack).(*Tracking)
serverStatus := ctx.Value(ctxServerStatus).(*Status)
defer func() {
connectionTracking.unregister <- extConn
serverStatus.ExtConnectionUnregister(extConn)
extConn.Close()
}()
connectionTable := ctx.Value(ctxConnectionTable).(*Table)
//find the connection by domain name
conn, ok := connectionTable.ConnByDomain(hostname)
conn, ok := serverStatus.ConnectionTable.ConnByDomain(hostname)
if !ok {
//matching connection can not be found based on ConnByDomain
loginfo.Println("unable to match ", hostname, " to an existing connection")
@ -289,7 +292,7 @@ func handleExternalHTTPRequest(ctx context.Context, extConn *WedgeConn, hostname
}
track := NewTrack(extConn, hostname)
connectionTracking.register <- track
serverStatus.ExtConnectionRegister(track)
loginfo.Println("Domain Accepted", hostname, extConn.RemoteAddr().String())
@ -322,10 +325,11 @@ func handleExternalHTTPRequest(ctx context.Context, extConn *WedgeConn, hostname
p.Data.AppendBytes(buffer[0:cnt])
buf := p.PackV1()
loginfo.Println(hex.Dump(buf.Bytes()))
//loginfo.Println(hex.Dump(buf.Bytes()))
//Bundle up the send request and dispatch
sendTrack := NewSendTrack(buf.Bytes(), hostname)
conn.SendCh() <- sendTrack
serverStatus.SendExtRequest(conn, sendTrack)
_, err = extConn.Discard(cnt)
if err != nil {
@ -341,7 +345,9 @@ func handleExternalHTTPRequest(ctx context.Context, extConn *WedgeConn, hostname
// - auth will happen again since we were just peeking at the token.
func handleWssClient(ctx context.Context, oneConn *oneConnListener) {
secretKey := ctx.Value(ctxSecretKey).(string)
connectionTable := ctx.Value(ctxConnectionTable).(*Table)
serverStatus := ctx.Value(ctxServerStatus).(*Status)
//connectionTable := ctx.Value(ctxConnectionTable).(*Table)
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
@ -380,9 +386,10 @@ func handleWssClient(ctx context.Context, oneConn *oneConnListener) {
//newConnection := connection.NewConnection(connectionTable, conn, r.RemoteAddr, domains)
connectionTrack := ctx.Value(ctxConnectionTrack).(*Tracking)
newRegistration := NewRegistration(conn, r.RemoteAddr, domains, connectionTrack)
connectionTable.Register() <- newRegistration
//connectionTrack := ctx.Value(ctxConnectionTrack).(*Tracking)
newRegistration := NewRegistration(conn, r.RemoteAddr, domains, serverStatus.ConnectionTracking)
serverStatus.WSSConnectionRegister(newRegistration)
ok = <-newRegistration.CommCh()
if !ok {
loginfo.Println("connection registration failed ", newRegistration)

View File

@ -57,23 +57,24 @@ type GenericListeners struct {
adminHostName string
cancelCheck int
lbDefaultMethod string
serverStatus *Status
}
//NewGenerListeners --
func NewGenerListeners(ctx context.Context, connectionTable *Table, connectionTrack *Tracking, secretKey string, certbundle tls.Certificate,
wssHostName string, adminHostName string, cancelCheck int, lbDefaultMethod string) (p *GenericListeners) {
func NewGenerListeners(ctx context.Context, secretKey string, certbundle tls.Certificate, serverStatus *Status) (p *GenericListeners) {
p = new(GenericListeners)
p.listeners = make(map[*net.Listener]int)
p.ctx = ctx
p.connnectionTable = connectionTable
p.connectionTracking = connectionTrack
p.connnectionTable = serverStatus.ConnectionTable
p.connectionTracking = serverStatus.ConnectionTracking
p.secretKey = secretKey
p.certbundle = certbundle
p.register = make(chan *ListenerRegistration)
p.wssHostName = wssHostName
p.adminHostName = adminHostName
p.cancelCheck = cancelCheck
p.lbDefaultMethod = lbDefaultMethod
p.wssHostName = serverStatus.WssDomain
p.adminHostName = serverStatus.AdminDomain
p.cancelCheck = serverStatus.DeadTime.cancelcheck
p.lbDefaultMethod = serverStatus.LoadbalanceDefaultMethod
p.serverStatus = serverStatus
return
}
@ -86,7 +87,6 @@ func (gl *GenericListeners) Run(ctx context.Context, initialPort int) {
config := &tls.Config{Certificates: []tls.Certificate{gl.certbundle}}
ctx = context.WithValue(ctx, ctxSecretKey, gl.secretKey)
ctx = context.WithValue(ctx, ctxConnectionTable, gl.connnectionTable)
loginfo.Println(gl.connectionTracking)
@ -97,6 +97,7 @@ func (gl *GenericListeners) Run(ctx context.Context, initialPort int) {
ctx = context.WithValue(ctx, ctxAdminHostName, gl.adminHostName)
ctx = context.WithValue(ctx, ctxCancelCheck, gl.cancelCheck)
ctx = context.WithValue(ctx, ctxLoadbalanceDefaultMethod, gl.lbDefaultMethod)
ctx = context.WithValue(ctx, ctxServerStatus, gl.serverStatus)
go func(ctx context.Context) {
for {

View File

@ -0,0 +1,78 @@
package genericlistener
import (
"context"
"time"
)
//Status --
type Status struct {
ctx context.Context
Name string
StartTime time.Time
WssDomain string
AdminDomain string
DeadTime *StatusDeadTime
ConnectionTracking *Tracking
ConnectionTable *Table
GenericListeners *GenericListeners
LoadbalanceDefaultMethod string
AdminStats *TrafficStats
TrafficStats *TrafficStats
ExtConnections *ConnectionStats
WSSConnections *ConnectionStats
}
//NewStatus --
func NewStatus(ctx context.Context) (p *Status) {
p = new(Status)
p.ctx = ctx
p.AdminStats = new(TrafficStats)
p.TrafficStats = new(TrafficStats)
p.ExtConnections = new(ConnectionStats)
p.WSSConnections = new(ConnectionStats)
return
}
// South Facing Functions
//WSSConnectionRegister --
func (p *Status) WSSConnectionRegister(newRegistration *Registration) {
p.ConnectionTable.Register() <- newRegistration
p.WSSConnections.IncConnections()
}
//WSSConnectionUnregister --
//unregisters a south facing connection
//intercept and update global statistics
func (p *Status) WSSConnectionUnregister() {
}
// External Facing Functions
//ExtConnectionRegister --
//registers an ext facing connection
//intercept and update global statistics
func (p *Status) ExtConnectionRegister(newTrack *Track) {
p.ConnectionTracking.register <- newTrack
p.ExtConnections.IncConnections()
}
//ExtConnectionUnregister --
//unregisters an ext facing connection
//intercept and update global statistics
func (p *Status) ExtConnectionUnregister(extConn *WedgeConn) {
p.ConnectionTracking.unregister <- extConn
p.ExtConnections.DecConnections()
}
//SendExtRequest --
//sends a request to a south facing connection
//intercept the send, update our global stats
func (p *Status) SendExtRequest(conn *Connection, sendTrack *SendTrack) {
p.TrafficStats.IncRequests()
p.TrafficStats.AddBytesOut(int64(len(sendTrack.data)))
conn.SendCh() <- sendTrack
}

View File

@ -0,0 +1,17 @@
package genericlistener
//StatusDeadTime -- structure for deadtime configuration
type StatusDeadTime struct {
dwell int
idle int
cancelcheck int
}
//NewStatusDeadTime -- constructor
func NewStatusDeadTime(dwell int, idle int, cancelcheck int) (p *StatusDeadTime) {
p = new(StatusDeadTime)
p.dwell = dwell
p.idle = idle
p.cancelcheck = cancelcheck
return
}

View File

@ -0,0 +1,23 @@
package genericlistener
//ConnectionStats --
type ConnectionStats struct {
Connections int64
}
//NewConnectionStats -- Consttuctor
func NewConnectionStats() (p *ConnectionStats) {
p = new(ConnectionStats)
p.Connections = 0
return
}
//IncConnections --
func (p *ConnectionStats) IncConnections() {
p.Connections++
}
//DecConnections --
func (p *ConnectionStats) DecConnections() {
p.Connections--
}

View File

@ -0,0 +1,40 @@
package genericlistener
//TrafficStats --
type TrafficStats struct {
Requests int64
Responses int64
BytesIn int64
BytesOut int64
}
//NewTrafficStats -- Consttuctor
func NewTrafficStats() (p *TrafficStats) {
p = new(TrafficStats)
p.Requests = 0
p.Responses = 0
p.BytesIn = 0
p.BytesOut = 0
return
}
//IncRequests --
func (p *TrafficStats) IncRequests() {
p.Requests++
}
//IncResponses --
func (p *TrafficStats) IncResponses() {
p.Responses++
}
//AddBytesIn --
func (p *TrafficStats) AddBytesIn(count int64) {
p.BytesIn = p.BytesIn + count
}
//AddBytesOut --
func (p *TrafficStats) AddBytesOut(count int64) {
p.BytesOut = p.BytesOut + count
}