satellite/metainfo: collect versions of user tools
We want to know usage statistics for our main tools like uplink-cli or rclone. Initially we will collect only usage stats without relation to specific process e.g. download or upload. Change-Id: I203b1a6c07ae014e710368f77163f13fdf10763c
This commit is contained in:
parent
e0b3c7152b
commit
eb0d08d59b
2
go.mod
2
go.mod
@ -5,6 +5,7 @@ go 1.17
|
|||||||
require (
|
require (
|
||||||
github.com/alessio/shellescape v1.2.2
|
github.com/alessio/shellescape v1.2.2
|
||||||
github.com/alicebob/miniredis/v2 v2.13.3
|
github.com/alicebob/miniredis/v2 v2.13.3
|
||||||
|
github.com/blang/semver v3.5.1+incompatible
|
||||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
||||||
github.com/calebcase/tmpfile v1.0.3
|
github.com/calebcase/tmpfile v1.0.3
|
||||||
github.com/cheggaaa/pb/v3 v3.0.5
|
github.com/cheggaaa/pb/v3 v3.0.5
|
||||||
@ -60,7 +61,6 @@ require (
|
|||||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
|
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
|
||||||
github.com/apache/thrift v0.12.0 // indirect
|
github.com/apache/thrift v0.12.0 // indirect
|
||||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||||
|
@ -138,7 +138,7 @@ func NewEndpoint(log *zap.Logger, buckets *buckets.Service, metabaseDB *metabase
|
|||||||
revocations: revocations,
|
revocations: revocations,
|
||||||
defaultRS: defaultRSScheme,
|
defaultRS: defaultRSScheme,
|
||||||
config: config,
|
config: config,
|
||||||
versionCollector: newVersionCollector(),
|
versionCollector: newVersionCollector(log),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
package metainfo
|
package metainfo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
|
"github.com/blang/semver"
|
||||||
"github.com/spacemonkeygo/monkit/v3"
|
"github.com/spacemonkeygo/monkit/v3"
|
||||||
"github.com/zeebo/errs"
|
"github.com/zeebo/errs"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"storj.io/common/useragent"
|
"storj.io/common/useragent"
|
||||||
)
|
)
|
||||||
@ -16,53 +18,66 @@ import (
|
|||||||
const uplinkProduct = "uplink"
|
const uplinkProduct = "uplink"
|
||||||
|
|
||||||
type versionOccurrence struct {
|
type versionOccurrence struct {
|
||||||
|
Product string
|
||||||
Version string
|
Version string
|
||||||
Method string
|
Method string
|
||||||
}
|
}
|
||||||
|
|
||||||
type versionCollector struct {
|
type versionCollector struct {
|
||||||
mu sync.Mutex
|
log *zap.Logger
|
||||||
versions map[versionOccurrence]*monkit.Meter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVersionCollector() *versionCollector {
|
func newVersionCollector(log *zap.Logger) *versionCollector {
|
||||||
return &versionCollector{
|
return &versionCollector{
|
||||||
versions: make(map[versionOccurrence]*monkit.Meter),
|
log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vc *versionCollector) collect(useragentRaw []byte, method string) error {
|
func (vc *versionCollector) collect(useragentRaw []byte, method string) error {
|
||||||
var meter *monkit.Meter
|
if len(useragentRaw) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
version := "unknown"
|
entries, err := useragent.ParseEntries(useragentRaw)
|
||||||
if len(useragentRaw) != 0 {
|
if err != nil {
|
||||||
entries, err := useragent.ParseEntries(useragentRaw)
|
return errs.New("invalid user agent %q: %v", string(useragentRaw), err)
|
||||||
if err != nil {
|
}
|
||||||
return errs.New("invalid user agent %q: %v", string(useragentRaw), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
if strings.EqualFold(entry.Product, uplinkProduct) {
|
if strings.EqualFold(entry.Product, uplinkProduct) {
|
||||||
version = entry.Version
|
vo := versionOccurrence{
|
||||||
break
|
Product: entry.Product,
|
||||||
|
Version: entry.Version,
|
||||||
|
Method: method,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vc.sendUplinkMetric(vo)
|
||||||
|
} else {
|
||||||
|
// for other user agents monitor only product
|
||||||
|
product := entry.Product
|
||||||
|
if product == "" {
|
||||||
|
product = "unknown"
|
||||||
|
}
|
||||||
|
mon.Meter("user_agents", monkit.NewSeriesTag("user_agent", product)).Mark(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vo := versionOccurrence{
|
|
||||||
Version: version,
|
|
||||||
Method: method,
|
|
||||||
}
|
|
||||||
|
|
||||||
vc.mu.Lock()
|
|
||||||
meter, ok := vc.versions[vo]
|
|
||||||
if !ok {
|
|
||||||
meter = monkit.NewMeter(monkit.NewSeriesKey("uplink_versions").WithTag("version", version).WithTag("method", method))
|
|
||||||
mon.Chain(meter)
|
|
||||||
vc.versions[vo] = meter
|
|
||||||
}
|
|
||||||
vc.mu.Unlock()
|
|
||||||
|
|
||||||
meter.Mark(1)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vc *versionCollector) sendUplinkMetric(vo versionOccurrence) {
|
||||||
|
if vo.Version == "" {
|
||||||
|
vo.Version = "unknown"
|
||||||
|
} else {
|
||||||
|
// use only major and minor to avoid using too many resources and
|
||||||
|
// minimize risk of abusing by sending lots of different versions
|
||||||
|
semVer, err := semver.ParseTolerant(vo.Version)
|
||||||
|
if err != nil {
|
||||||
|
vc.log.Warn("invalid uplink library user agent version", zap.String("version", vo.Version), zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vo.Version = fmt.Sprintf("v%d.%d", semVer.Major, semVer.Minor)
|
||||||
|
}
|
||||||
|
|
||||||
|
mon.Meter("uplink_versions", monkit.NewSeriesTag("version", vo.Version), monkit.NewSeriesTag("method", vo.Method)).Mark(1)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user