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

Adding analytics for usage metrics #136

Merged
merged 3 commits into from
Sep 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
# This makefile is meant for humans

VERSION := $(shell git describe --tags --always --dirty="-dev")
LDFLAGS := -ldflags='-X "main.Version=$(VERSION)"'
ANALYTICS_WRITE_KEY ?=
LDFLAGS := -ldflags='-X "main.Version=$(VERSION)" -X "main.AnalyticsWriteKey=$(ANALYTICS_WRITE_KEY)"'

test: | govendor
govendor sync
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ To configure chamber to use the S3 backend, set `CHAMBER_SECRET_BACKEND` to `S3`

This feature is experimental, and not currently meant for production work.

## Analytics

`chamber` includes some usage analytics code which Segment uses internally for tracking usage of internal tools. This analytics code is turned off by default, and can only be enabled via a linker flag at build time, which we do not set for public github releases.

## Releasing

To cut a new release, just push a tag named `v<semver>` where `<semver>` is a
Expand Down
14 changes: 14 additions & 0 deletions cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"strings"

"github.com/pkg/errors"
analytics "github.com/segmentio/analytics-go"

Choose a reason for hiding this comment

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

I recommend using https://github.com/segmentio/analytics-go/tree/v3.0. We've already deprecated v2 and are just waiting for until the deprecation date to merge v3.0 into master.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yup! I'm using v3 :)

Choose a reason for hiding this comment

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

ah 👍

"github.com/segmentio/chamber/store"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -31,6 +32,19 @@ func delete(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "Failed to validate key")
}

if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "delete").
Set("chamber-version", chamberVersion).
Set("service", service).
Set("key", key).
Set("backend", backend),
})
}

secretStore := getSecretStore()
secretId := store.SecretId{
Service: service,
Expand Down
13 changes: 13 additions & 0 deletions cmd/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/pkg/errors"
analytics "github.com/segmentio/analytics-go"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -37,6 +38,18 @@ func execRun(cmd *cobra.Command, args []string) error {
dashIx := cmd.ArgsLenAtDash()
services, command, commandArgs := args[:dashIx], args[dashIx], args[dashIx+1:]

if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "exec").
Set("chamber-version", chamberVersion).
Set("services", services).
Set("backend", backend),
})
}

env := environ(os.Environ())
secretStore := getSecretStore()
envVarKeys := make([]string, 0)
Expand Down
13 changes: 13 additions & 0 deletions cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/magiconair/properties"
"github.com/pkg/errors"
analytics "github.com/segmentio/analytics-go"
"github.com/spf13/cobra"
)

Expand All @@ -37,6 +38,18 @@ func init() {
func runExport(cmd *cobra.Command, args []string) error {
var err error

if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "export").
Set("chamber-version", chamberVersion).
Set("services", args).
Set("backend", backend),
})
}

secretStore := getSecretStore()
params := make(map[string]string)
for _, service := range args {
Expand Down
14 changes: 14 additions & 0 deletions cmd/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"text/tabwriter"

"github.com/pkg/errors"
analytics "github.com/segmentio/analytics-go"
"github.com/segmentio/chamber/store"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -34,6 +35,19 @@ func history(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "Failed to validate key")
}

if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "history").
Set("chamber-version", chamberVersion).
Set("service", service).
Set("key", key).
Set("backend", backend),
})
}

secretStore := getSecretStore()
secretId := store.SecretId{
Service: service,
Expand Down
13 changes: 13 additions & 0 deletions cmd/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"

"github.com/pkg/errors"
analytics "github.com/segmentio/analytics-go"
"github.com/segmentio/chamber/store"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -51,6 +52,18 @@ func importRun(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "Failed to decode input as json")
}

if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "import").
Set("chamber-version", chamberVersion).
Set("service", service).
Set("backend", backend),
})
}

secretStore := getSecretStore()

for key, value := range toBeImported {
Expand Down
13 changes: 13 additions & 0 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"text/tabwriter"

"github.com/pkg/errors"
analytics "github.com/segmentio/analytics-go"
"github.com/spf13/cobra"
)

Expand All @@ -33,6 +34,18 @@ func list(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "Failed to validate service")
}

if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "list").
Set("chamber-version", chamberVersion).
Set("service", service).
Set("backend", backend),
})
}

secretStore := getSecretStore()
secrets, err := secretStore.List(service, withValues)
if err != nil {
Expand Down
14 changes: 14 additions & 0 deletions cmd/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"text/tabwriter"

"github.com/pkg/errors"
analytics "github.com/segmentio/analytics-go"
"github.com/segmentio/chamber/store"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -41,6 +42,19 @@ func read(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "Failed to validate key")
}

if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "read").
Set("chamber-version", chamberVersion).
Set("service", service).
Set("key", key).
Set("backend", backend),
})
}

secretStore := getSecretStore()

secretId := store.SecretId{
Expand Down
47 changes: 41 additions & 6 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"regexp"
"strings"

analytics "github.com/segmentio/analytics-go"
"github.com/segmentio/chamber/store"
"github.com/spf13/cobra"
)
Expand All @@ -19,6 +20,12 @@ var (
verbose bool
numRetries int
chamberVersion string
backend string

analyticsEnabled bool
analyticsWriteKey string
analyticsClient analytics.Client
username string
)

const (
Expand All @@ -40,9 +47,11 @@ var Backends = []string{SSMBackend, S3Backend}

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "chamber",
Short: "CLI for storing secrets",
SilenceUsage: true,
Use: "chamber",
Short: "CLI for storing secrets",
SilenceUsage: true,
PersistentPreRun: prerun,
PersistentPostRun: postrun,
}

func init() {
Expand All @@ -52,8 +61,12 @@ func init() {

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute(vers string) {
func Execute(vers string, writeKey string) {
chamberVersion = vers

analyticsWriteKey = writeKey
analyticsEnabled = analyticsWriteKey != ""

if cmd, err := RootCmd.ExecuteC(); err != nil {
if strings.Contains(err.Error(), "arg(s)") || strings.Contains(err.Error(), "usage") {
cmd.Usage()
Expand Down Expand Up @@ -85,8 +98,6 @@ func validateKey(key string) error {
}

func getSecretStore() store.Store {
backend := strings.ToUpper(os.Getenv(BackendEnvVar))

var s store.Store
switch backend {
case S3Backend:
Expand All @@ -98,3 +109,27 @@ func getSecretStore() store.Store {
}
return s
}

func prerun(cmd *cobra.Command, args []string) {
backend = strings.ToUpper(os.Getenv(BackendEnvVar))

if analyticsEnabled {
// set up analytics client
analyticsClient, _ = analytics.NewWithConfig(analyticsWriteKey, analytics.Config{
BatchSize: 1,
})

username = os.Getenv("USER")
analyticsClient.Enqueue(analytics.Identify{
UserId: username,
Traits: analytics.NewTraits().
Set("chamber-version", chamberVersion),
})
}
}

func postrun(cmd *cobra.Command, args []string) {
if analyticsEnabled && analyticsClient != nil {
analyticsClient.Close()
}
}
11 changes: 11 additions & 0 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"

analytics "github.com/segmentio/analytics-go"
"github.com/spf13/cobra"
)

Expand All @@ -20,5 +21,15 @@ func init() {

func versionRun(cmd *cobra.Command, args []string) error {
fmt.Fprintf(os.Stdout, "chamber %s\n", chamberVersion)
if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "version").
Set("chamber-version", chamberVersion).
Set("backend", backend),
})
}
return nil
}
14 changes: 14 additions & 0 deletions cmd/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"

"github.com/pkg/errors"
analytics "github.com/segmentio/analytics-go"
"github.com/segmentio/chamber/store"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -39,6 +40,19 @@ func write(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "Failed to validate key")
}

if analyticsEnabled && analyticsClient != nil {
analyticsClient.Enqueue(analytics.Track{
UserId: username,
Event: "Ran Command",
Properties: analytics.NewProperties().
Set("command", "write").
Set("chamber-version", chamberVersion).
Set("service", service).
Set("backend", backend).
Set("key", key),
})
}

value := args[2]
if value == "-" {
// Read value from standard input
Expand Down
5 changes: 3 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import "github.com/segmentio/chamber/cmd"

var (
// This is updated by linker flags during build
Version = "dev"
Version = "dev"
AnalyticsWriteKey = ""
)

func main() {
cmd.Execute(Version)
cmd.Execute(Version, AnalyticsWriteKey)
}
Loading