graphql-engine/cli/telemetry/telemetry.go

122 lines
2.7 KiB
Go

package telemetry
import (
"runtime"
"sync"
"time"
"github.com/Masterminds/semver"
"github.com/parnurzeal/gorequest"
"github.com/sirupsen/logrus"
)
// Waiter waits for telemetry ops to complete, if required
var Waiter sync.WaitGroup
// Endpoint is where telemetry data is sent.
const Endpoint = "https://telemetry.hasura.io/v1/http"
// Topic is the name under which telemetry is sent.
var Topic = "cli_test"
type requestPayload struct {
Topic string `json:"topic"`
Data `json:"data"`
}
// Data holds all info collected and transmitted
type Data struct {
// UUID used for telemetry, generated on first run.
UUID string `json:"uuid"`
// UUID obtained from server.
ServerUUID string `json:"server_uuid"`
// Unique id for the current execution.
ExecutionID string `json:"execution_id"`
// OS platform and architecture.
OSPlatform string `json:"os_platform"`
OSArch string `json:"os_arch"`
// Current cli version.
Version string `json:"version"`
// Current Server version.
ServerVersion string `json:"server_version"`
// Command being executed.
Command string `json:"command"`
// Indicates whether the execution resulted in an error or not.
IsError bool `json:"is_error"`
// Any additional payload information.
Payload map[string]interface{} `json:"payload"`
// Additional objects - mandatory
Logger *logrus.Logger `json:"-"`
// IsBeamed indicates if this data is already beamed or not.
IsBeamed bool `json:"-"`
// CanBeam indicates if data can be beamed or not, e.g. disabled telemetry.
CanBeam bool `json:"-"`
}
// BuildEvent returns a Data object which represent a telemetry event
func BuildEvent() *Data {
return &Data{
OSPlatform: runtime.GOOS,
OSArch: runtime.GOARCH,
CanBeam: true,
}
}
// Beam the telemetry data
func (d *Data) Beam() {
// to be on the safe side, create a new logger if a logger
// is not passed
if d.Logger == nil {
d.Logger = logrus.New()
}
if !d.CanBeam {
d.Logger.Debugf("telemetry: disabled, not beaming any data")
return
}
if !d.IsBeamed {
beam(d, d.Logger)
} else {
d.Logger.Debugf("telemetry: data already beamed")
}
}
func getTopic(v string) string {
topic := "cli_test"
if _, err := semver.NewVersion(v); err == nil {
topic = "cli"
}
return topic
}
func beam(d *Data, log *logrus.Logger) {
d.IsBeamed = true
p := requestPayload{
Topic: getTopic(d.Version),
Data: *d,
}
tick := time.Now()
_, _, err := gorequest.New().
Post(Endpoint).
Timeout(2 * time.Second).
Send(p).
End()
if err != nil {
log.Debugf("telemetry: beaming payload failed: %v", err)
} else {
tock := time.Now()
delta := tock.Sub(tick)
log.WithField("isError", d.IsError).WithField("time", delta.String()).Debug("telemetry: beamed")
}
}