-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
98d6e7b
commit 8ddf624
Showing
6 changed files
with
56 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,115 +1,91 @@ | ||
package statistics | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"github.com/inexio/thola/core/network" | ||
"github.com/labstack/echo" | ||
"github.com/thoas/stats" | ||
"math" | ||
"net/http" | ||
"strings" | ||
"sync" | ||
"time" | ||
) | ||
|
||
var statistics struct { | ||
var stats statistics | ||
|
||
type statistics struct { | ||
sync.Once | ||
sync.RWMutex | ||
|
||
mw *stats.Stats | ||
tholaData *tholaData | ||
startTime time.Time | ||
startTime time.Time | ||
successfulCounter int | ||
failedCounter int | ||
totalResponseTime time.Duration | ||
} | ||
|
||
type tholaData struct { | ||
sync.RWMutex | ||
|
||
SNMPRequests uint64 | ||
// Statistics includes stats of all requests handled by the api | ||
type Statistics struct { | ||
UpSince time.Time | ||
TotalCount int | ||
SuccessfulCounter int | ||
FailedCounter int | ||
AverageResponseTime float64 | ||
} | ||
|
||
func handlerFunc(h http.Handler) http.Handler { | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
beginning, _ := statistics.mw.Begin(w) | ||
beginning := time.Now() | ||
|
||
h.ServeHTTP(w, r) | ||
|
||
echoRes := w.(*echo.Response) | ||
|
||
statistics.mw.End(beginning, stats.WithStatusCode(echoRes.Status), stats.WithSize(int(echoRes.Size))) | ||
stats.add(beginning, echoRes.Status) | ||
}) | ||
} | ||
|
||
// Middleware represents an API middleware | ||
func Middleware() echo.MiddlewareFunc { | ||
statistics.Do(func() { | ||
statistics.mw = stats.New() | ||
statistics.startTime = time.Now() | ||
statistics.tholaData = &tholaData{} | ||
stats.Do(func() { | ||
stats.init() | ||
}) | ||
return echo.WrapMiddleware(handlerFunc) | ||
} | ||
|
||
// Stats includes stats of all requests handled by the api | ||
type Stats struct { | ||
Pid int | ||
UpSince time.Time | ||
Requests RequestsStats | ||
func (s *statistics) init() { | ||
s.startTime = time.Now() | ||
} | ||
|
||
// RequestsStats includes request stats of all requests handled by the api | ||
type RequestsStats struct { | ||
TotalCount int | ||
SuccessfulCounter int | ||
FailedCounter int | ||
StatusCodeCount map[string]int | ||
SNMPRequests uint64 | ||
AverageResponseTime float64 // this is the average response time of all time since the api started | ||
AverageResponseSize int64 // same for response size | ||
func (s *statistics) add(startTime time.Time, statusCode int) { | ||
s.Lock() | ||
defer s.Unlock() | ||
|
||
} | ||
s.totalResponseTime += time.Since(startTime) | ||
|
||
// GetStatistics returns the current statistics | ||
func GetStatistics() (Stats, error) { | ||
// this error can be removed when there are other stats than request stats | ||
if statistics.mw == nil || statistics.tholaData == nil { | ||
return Stats{}, errors.New("no request stats available") | ||
} | ||
data := statistics.mw.Data() | ||
var s Stats | ||
s.Pid = data.Pid | ||
s.UpSince = statistics.startTime | ||
|
||
s.Requests.TotalCount = data.TotalCount | ||
s.Requests.StatusCodeCount = data.StatusCodeCount | ||
for code, count := range data.TotalStatusCodeCount { | ||
if strings.HasPrefix(code, "2") { | ||
s.Requests.SuccessfulCounter += count | ||
} else { | ||
s.Requests.FailedCounter += count | ||
} | ||
if statusCode >= 200 && statusCode <= 299 { | ||
s.successfulCounter++ | ||
} else { | ||
s.failedCounter++ | ||
} | ||
|
||
s.Requests.AverageResponseTime = data.AverageResponseTimeSec | ||
s.Requests.AverageResponseSize = data.AverageResponseSize | ||
|
||
statistics.tholaData.RLock() | ||
defer statistics.tholaData.RUnlock() | ||
s.Requests.SNMPRequests = statistics.tholaData.SNMPRequests | ||
|
||
return s, nil | ||
} | ||
|
||
// AddRequestStatistics adds statistics which are only available while processing the request | ||
func AddRequestStatistics(ctx context.Context) { | ||
if statistics.tholaData == nil { | ||
return | ||
// GetStatistics returns the current statistics | ||
func GetStatistics() (Statistics, error) { | ||
stats.RLock() | ||
defer stats.RUnlock() | ||
|
||
s := Statistics{ | ||
UpSince: stats.startTime, | ||
TotalCount: stats.successfulCounter + stats.failedCounter, | ||
SuccessfulCounter: stats.successfulCounter, | ||
FailedCounter: stats.failedCounter, | ||
AverageResponseTime: 0, | ||
} | ||
|
||
con, ok := network.DeviceConnectionFromContext(ctx) | ||
if !ok || con.SNMP == nil { | ||
return | ||
if s.TotalCount == 0 { | ||
return s, nil | ||
} else { | ||
avgNs := int64(stats.totalResponseTime) / int64(s.TotalCount) | ||
avgSec := float64(avgNs) / float64(time.Second) | ||
s.AverageResponseTime = math.Floor(avgSec*1000) / 1000 | ||
} | ||
|
||
statistics.tholaData.Lock() | ||
defer statistics.tholaData.Unlock() | ||
statistics.tholaData.SNMPRequests += uint64(con.SNMP.SnmpClient.GetRequestCounter()) | ||
return s, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters