Skip to content

Commit

Permalink
removed external statistics module
Browse files Browse the repository at this point in the history
  • Loading branch information
TheFireMike committed Feb 3, 2021
1 parent 98d6e7b commit 8ddf624
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 100 deletions.
120 changes: 48 additions & 72 deletions api/statistics/statistics.go
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
}
17 changes: 4 additions & 13 deletions core/network/snmp_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ import (

// SNMPClient is used to communicate via snmp.
type SNMPClient struct {
client *gosnmp.GoSNMP
useCache bool
cache requestCache
requestCounter int
client *gosnmp.GoSNMP
useCache bool
cache requestCache
}

type snmpClientCreation struct {
Expand Down Expand Up @@ -183,7 +182,7 @@ func NewSNMPClient(ctx context.Context, ipAddress, snmpVersion, community string
client.Retries = 3
client.ExponentialTimeout = true

return &SNMPClient{client: client, useCache: true, cache: newRequestCache(), requestCounter: 1}, nil
return &SNMPClient{client: client, useCache: true, cache: newRequestCache()}, nil
}

func getGoSNMPVersion(version string) (gosnmp.SnmpVersion, error) {
Expand Down Expand Up @@ -228,7 +227,6 @@ func (s *SNMPClient) SNMPGet(ctx context.Context, oid ...string) ([]SNMPResponse
if err != nil {
return nil, errors.Wrap(err, "error during snmpget")
}
s.requestCounter += len(reqOIDs)
}

successful := false
Expand Down Expand Up @@ -281,7 +279,6 @@ func (s *SNMPClient) SNMPWalk(ctx context.Context, oid string) ([]SNMPResponse,

var res []SNMPResponse
for _, currentResponse := range response {
s.requestCounter++
snmpResponse := SNMPResponse{}
snmpResponse.oid = currentResponse.Name
snmpResponse.value = currentResponse.Value
Expand Down Expand Up @@ -348,12 +345,6 @@ func (s *SNMPClient) SetMaxRepetitions(maxRepetitions uint8) {
s.client.MaxRepetitions = maxRepetitions
}

// GetRequestCounter returns the amount of snmp requests
// snmp walks are weighted by the amount of results
func (s *SNMPClient) GetRequestCounter() int {
return s.requestCounter
}

// SNMPResponse is the response returned for a single snmp request.
type SNMPResponse struct {
oid string
Expand Down
14 changes: 4 additions & 10 deletions core/request/check_thola_server_request_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,25 @@ func (r *CheckTholaServerRequest) process(ctx context.Context) (Response, error)
return &CheckResponse{r.mon.GetInfo()}, nil
}

err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("total_request_counter", stats.Requests.TotalCount, "c"))
err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("total_request_counter", stats.TotalCount, "c"))
if r.mon.UpdateStatusOnError(err, monitoringplugin.UNKNOWN, "error while adding performance data point", true) {
r.mon.PrintPerformanceData(false)
return &CheckResponse{r.mon.GetInfo()}, nil
}

err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("successful_request_counter", stats.Requests.SuccessfulCounter, "c"))
err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("successful_request_counter", stats.SuccessfulCounter, "c"))
if r.mon.UpdateStatusOnError(err, monitoringplugin.UNKNOWN, "error while adding performance data point", true) {
r.mon.PrintPerformanceData(false)
return &CheckResponse{r.mon.GetInfo()}, nil
}

err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("failed_request_counter", stats.Requests.FailedCounter, "c"))
err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("failed_request_counter", stats.FailedCounter, "c"))
if r.mon.UpdateStatusOnError(err, monitoringplugin.UNKNOWN, "error while adding performance data point", true) {
r.mon.PrintPerformanceData(false)
return &CheckResponse{r.mon.GetInfo()}, nil
}

err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("average_response_time", stats.Requests.AverageResponseTime, "s"))
if r.mon.UpdateStatusOnError(err, monitoringplugin.UNKNOWN, "error while adding performance data point", true) {
r.mon.PrintPerformanceData(false)
return &CheckResponse{r.mon.GetInfo()}, nil
}

err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("snmp_request_counter", stats.Requests.SNMPRequests, "c"))
err = r.mon.AddPerformanceDataPoint(monitoringplugin.NewPerformanceDataPoint("average_response_time", stats.AverageResponseTime, "s"))
if r.mon.UpdateStatusOnError(err, monitoringplugin.UNKNOWN, "error while adding performance data point", true) {
r.mon.PrintPerformanceData(false)
return &CheckResponse{r.mon.GetInfo()}, nil
Expand Down
2 changes: 0 additions & 2 deletions core/request/process_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package request
import (
"context"
"fmt"
"github.com/inexio/thola/api/statistics"
"github.com/inexio/thola/core/network"
"github.com/pkg/errors"
"strconv"
Expand Down Expand Up @@ -66,7 +65,6 @@ func processRequest(ctx context.Context, request Request, responseChan chan resp
}
defer con.CloseConnections()
ctx = network.NewContextWithDeviceConnection(ctx, con)
defer statistics.AddRequestStatistics(ctx)
res, err := request.process(ctx)
responseChan <- response{
res: res,
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.6.1
github.com/thoas/stats v0.0.0-20190407194641-965cb2de1678
github.com/ulule/limiter/v3 v3.5.0
github.com/valyala/fasttemplate v1.2.1 // indirect
golang.org/x/text v0.3.3
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,6 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/thoas/stats v0.0.0-20190407194641-965cb2de1678 h1:kFej3rMKjbzysHYvLmv5iOlbRymDMkNJxbovYb/iP0c=
github.com/thoas/stats v0.0.0-20190407194641-965cb2de1678/go.mod h1:GkZsNBOco11YY68OnXUARbSl26IOXXAeYf6ZKmSZR2M=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
Expand Down

0 comments on commit 8ddf624

Please sign in to comment.