Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collect analytics for voyager usages #133

Merged
merged 2 commits into from
Jun 1, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cmd/voyager/app/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
acw "github.com/appscode/k8s-addons/pkg/watcher"
"github.com/appscode/log"
"github.com/appscode/voyager/cmd/voyager/app/options"
"github.com/appscode/voyager/pkg/analytics"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
)
Expand All @@ -19,6 +20,10 @@ func Run(config *options.Config) {
log.Infoln("Configuration:", config)
defer runtime.HandleCrash()

if config.EnableAnalytics {
analytics.Enable()
}

c, err := clientcmd.BuildConfigFromFlags(config.Master, config.KubeConfig)
if err != nil {
fmt.Fprint(os.Stderr, err)
Expand All @@ -39,4 +44,6 @@ func Run(config *options.Config) {

log.Infoln("configuration loadded, running watcher")
go w.Run()

analytics.VoyagerStarted()
}
4 changes: 4 additions & 0 deletions cmd/voyager/app/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Config struct {
ClusterName string
LoadbalancerImageName string
IngressClass string
EnableAnalytics bool
}

func NewConfig() *Config {
Expand All @@ -20,6 +21,7 @@ func NewConfig() *Config {
ProviderName: "",
ClusterName: "",
LoadbalancerImageName: "appscode/haproxy:1.7.5-1.5.5",
EnableAnalytics: true,
}
}

Expand All @@ -32,4 +34,6 @@ func (s *Config) AddFlags(fs *pflag.FlagSet) {
fs.StringVarP(&s.LoadbalancerImageName, "haproxy-image", "h", s.LoadbalancerImageName, "haproxy image name to be run")

fs.StringVar(&s.IngressClass, "ingress-class", "", "Ingress class handled by voyager. Unset by default. Set to voyager to only handle ingress with annotation kubernetes.io/ingress.class=voyager.")

fs.BoolVar(&s.EnableAnalytics, "analytics", true, "Send analytical event to Google Analytics")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use EnableAnalytics here instead of true directly.

fs.BoolVar(&s.EnableAnalytics, "analytics", EnableAnalytics, "Send analytical event to Google Analytics")

}
36 changes: 35 additions & 1 deletion cmd/voyager/app/watcher.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package app

import (
"strings"

aci "github.com/appscode/k8s-addons/api"
"github.com/appscode/k8s-addons/pkg/events"
"github.com/appscode/k8s-addons/pkg/stash"
acw "github.com/appscode/k8s-addons/pkg/watcher"
"github.com/appscode/log"
"github.com/appscode/voyager/pkg/analytics"
"github.com/appscode/voyager/pkg/controller/certificates"
ingresscontroller "github.com/appscode/voyager/pkg/controller/ingress"
kapi "k8s.io/kubernetes/pkg/api"
Expand Down Expand Up @@ -102,12 +105,15 @@ func (w *Watcher) Dispatch(e *events.Event) error {
certController := certificates.NewController(w.Client, w.AppsCodeExtensionClient)
certController.Handle(e)
}
sendAnalytics(e, err)
return err
case events.Certificate:
var err error
if e.EventType.IsAdded() || e.EventType.IsUpdated() {
certController := certificates.NewController(w.Client, w.AppsCodeExtensionClient)
certController.Handle(e)
err = certController.Handle(e)
}
sendAnalytics(e, err)
case events.Service:
if e.EventType.IsAdded() || e.EventType.IsDeleted() {
return ingresscontroller.UpgradeAllEngress(
Expand Down Expand Up @@ -152,3 +158,31 @@ func (w *Watcher) Certificate() {

go certificates.NewCertificateSyncer(w.Client, w.AppsCodeExtensionClient).RunSync()
}

func sendAnalytics(e *events.Event, err error) {
switch e.ResourceType {
case events.Ingress, events.ExtendedIngress, events.Certificate:
if e.EventType.IsAdded() || e.EventType.IsDeleted() {
// without converting to specific type for each resource, we
// extract group version from resource SelfLink. This guaranties
// having GroupVersion.
gvk := e.MetaData.GetSelfLink()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you figure this out from ApiGroup & Name? Do we need to parse selfLink?

if len(gvk) > 0 {
gvk = strings.TrimPrefix(gvk, "/apis/")
idx := strings.Index(gvk, "/namespace")
if idx > 0 {
gvk = gvk[0:idx]
}
if len(gvk) > 0 && !strings.HasSuffix(gvk, "/") {
gvk += "/"
}
}

label := "success"
if err != nil {
label = "fail"
}
go analytics.Send(gvk+e.ResourceType.String(), strings.ToLower(e.EventType.String()), label)
}
}
}
12 changes: 10 additions & 2 deletions cmd/voyager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
_ "net/http/pprof"
"os"
"syscall"

"github.com/appscode/errors"
err_logger "github.com/appscode/errors/h/log"
Expand All @@ -12,6 +12,7 @@ import (
logs "github.com/appscode/log/golog"
"github.com/appscode/voyager/cmd/voyager/app"
"github.com/appscode/voyager/cmd/voyager/app/options"
"github.com/appscode/voyager/pkg/analytics"
"github.com/mikespook/golib/signal"
"github.com/spf13/pflag"
// Add fake package as a dependency to add this under vendor
Expand All @@ -38,7 +39,14 @@ func main() {

log.Infoln("Starting Voyager Controller...")
go app.Run(config)

sig := signal.New(nil)
sig.Bind(os.Interrupt, func() uint { return signal.BreakExit })
sig.Bind(syscall.SIGTERM, exit)
sig.Bind(syscall.SIGINT, exit)
sig.Wait()
}

func exit() uint {
analytics.VoyagerStopped()
return signal.BreakExit
}
67 changes: 67 additions & 0 deletions pkg/analytics/analytics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package analytics

import (
"strings"
"sync"

"github.com/appscode/log"
ga "github.com/jpillora/go-ogle-analytics"
)

const (
trackingID = "UA-62096468-13"
)

var (
mu sync.Mutex
client *ga.Client
)

func Enable() {
mu.Lock()
defer mu.Unlock()
client = mustNewClient()
}

func Disable() {
mu.Lock()
defer mu.Unlock()
client = nil
}

func send(e *ga.Event) {
mu.Lock()
c := client
mu.Unlock()

if c == nil {
return
}

// error is ignored intentionally. we try to send event to GA in a best effort approach.
c.Send(e)
}

func mustNewClient() *ga.Client {
client, err := ga.NewClient(trackingID)
if err != nil {
log.Fatalln(err)
}
return client
}

func VoyagerStarted() {
send(ga.NewEvent("operator", "started"))
}

func VoyagerStopped() {
send(ga.NewEvent("operator", "stopped"))
}

func Send(category, action string, label ...string) {
ev := ga.NewEvent(category, action)
if len(label) > 0 {
ev.Label(strings.Join(label, ","))
}
send(ev)
}