storj/satellite/metainfo/version_collector.go
Michał Niewrzał eb0d08d59b 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
2022-01-12 13:49:15 +00:00

84 lines
1.9 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package metainfo
import (
"fmt"
"strings"
"github.com/blang/semver"
"github.com/spacemonkeygo/monkit/v3"
"github.com/zeebo/errs"
"go.uber.org/zap"
"storj.io/common/useragent"
)
const uplinkProduct = "uplink"
type versionOccurrence struct {
Product string
Version string
Method string
}
type versionCollector struct {
log *zap.Logger
}
func newVersionCollector(log *zap.Logger) *versionCollector {
return &versionCollector{
log: log,
}
}
func (vc *versionCollector) collect(useragentRaw []byte, method string) error {
if len(useragentRaw) == 0 {
return nil
}
entries, err := useragent.ParseEntries(useragentRaw)
if err != nil {
return errs.New("invalid user agent %q: %v", string(useragentRaw), err)
}
for _, entry := range entries {
if strings.EqualFold(entry.Product, uplinkProduct) {
vo := versionOccurrence{
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)
}
}
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)
}