telemetry support

Fixes #832

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
This commit is contained in:
Andrea Luzzardi
2021-07-20 13:11:20 +02:00
parent eb78661620
commit 5bc0bff1b0
24 changed files with 378 additions and 32 deletions

View File

@@ -0,0 +1,87 @@
package common
import (
"context"
"crypto/sha256"
"fmt"
"strings"
"github.com/go-git/go-git/v5"
"github.com/spf13/cobra"
"go.dagger.io/dagger/state"
"go.dagger.io/dagger/telemetry"
)
// TrackCommand sends telemetry about a command execution
func TrackCommand(ctx context.Context, cmd *cobra.Command, props ...*telemetry.Property) chan struct{} {
props = append([]*telemetry.Property{
{
Name: "command",
Value: commandName(cmd),
},
}, props...)
return telemetry.TrackAsync(ctx, "Command Executed", props...)
}
func commandName(cmd *cobra.Command) string {
parts := []string{}
for c := cmd; c.Parent() != nil; c = c.Parent() {
parts = append([]string{c.Name()}, parts...)
}
return strings.Join(parts, " ")
}
// TrackWorkspaceCommand is like TrackCommand but includes workspace and
// optionally environment metadata.
func TrackWorkspaceCommand(ctx context.Context, cmd *cobra.Command, w *state.Workspace, env *state.State, props ...*telemetry.Property) chan struct{} {
props = append([]*telemetry.Property{
{
// Hash the repository URL for privacy
Name: "git_repository_hash",
Value: hash(gitRepoURL(w.Path)),
},
{
// The workspace path might contain the username (e.g. /home/user/workspace), so we hash itfor privacy.
Name: "workspace_path_hash",
Value: hash(w.Path),
},
}, props...)
if env != nil {
props = append([]*telemetry.Property{
{
Name: "environment_name",
Value: env.Name,
},
}, props...)
}
return TrackCommand(ctx, cmd, props...)
}
// hash returns the sha256 digest of the string
func hash(s string) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))
}
// gitRepoURL returns the git repository remote, if any.
func gitRepoURL(path string) string {
repo, err := git.PlainOpenWithOptions(path, &git.PlainOpenOptions{
DetectDotGit: true,
})
if err != nil {
return ""
}
origin, err := repo.Remote("origin")
if err != nil {
return ""
}
if urls := origin.Config().URLs; len(urls) > 0 {
return urls[0]
}
return ""
}

View File

@@ -38,6 +38,8 @@ var computeCmd = &cobra.Command{
lg := logger.New()
ctx := lg.WithContext(cmd.Context())
doneCh := common.TrackCommand(ctx, cmd)
st := &state.State{
Name: "FIXME",
Path: args[0],
@@ -191,6 +193,8 @@ var computeCmd = &cobra.Command{
return nil
})
<-doneCh
if err != nil {
lg.Fatal().Err(err).Msg("failed to up environment")
}

View File

@@ -269,6 +269,8 @@ var docCmd = &cobra.Command{
lg := logger.New()
ctx := lg.WithContext(cmd.Context())
doneCh := common.TrackCommand(ctx, cmd)
format := viper.GetString("format")
if format != textFormat &&
format != markdownFormat &&
@@ -297,6 +299,8 @@ var docCmd = &cobra.Command{
}
p := Parse(ctx, packageName, val)
fmt.Printf("%s", p.Format(format))
<-doneCh
},
}

View File

@@ -37,6 +37,12 @@ var editCmd = &cobra.Command{
workspace := common.CurrentWorkspace(ctx)
st := common.CurrentEnvironmentState(ctx, workspace)
lg = lg.With().
Str("environment", st.Name).
Logger()
doneCh := common.TrackWorkspaceCommand(ctx, cmd, workspace, st)
data, err := yaml.Marshal(st)
if err != nil {
lg.Fatal().Err(err).Msg("unable to marshal state")
@@ -80,6 +86,8 @@ var editCmd = &cobra.Command{
return nil
})
<-doneCh
if err != nil {
lg.Fatal().Err(err).Str("environment", st.Name).Msg("invalid input")
}

View File

@@ -5,6 +5,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/cmd/dagger/logger"
"go.dagger.io/dagger/state"
)
@@ -36,10 +37,13 @@ var initCmd = &cobra.Command{
dir = cwd
}
_, err := state.Init(ctx, dir)
workspace, err := state.Init(ctx, dir)
if err != nil {
lg.Fatal().Err(err).Msg("failed to initialize workspace")
}
<-common.TrackWorkspaceCommand(ctx, cmd, workspace, nil)
},
}

View File

@@ -3,7 +3,6 @@ package input
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/cmd/dagger/logger"
"go.dagger.io/dagger/state"
)
@@ -23,7 +22,7 @@ var containerCmd = &cobra.Command{
lg := logger.New()
ctx := lg.WithContext(cmd.Context())
updateEnvironmentInput(ctx, common.NewClient(ctx, false), args[0], state.DockerInput(args[1]))
updateEnvironmentInput(ctx, cmd, args[0], state.DockerInput(args[1]))
},
}

View File

@@ -43,7 +43,7 @@ var dirCmd = &cobra.Command{
p = "./" + p
}
updateEnvironmentInput(ctx, common.NewClient(ctx, false), args[0],
updateEnvironmentInput(ctx, cmd, args[0],
state.DirInput(
p,
viper.GetStringSlice("include"),

View File

@@ -3,7 +3,6 @@ package input
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/cmd/dagger/logger"
"go.dagger.io/dagger/state"
)
@@ -33,7 +32,7 @@ var gitCmd = &cobra.Command{
subDir = args[3]
}
updateEnvironmentInput(ctx, common.NewClient(ctx, false), args[0], state.GitInput(args[1], ref, subDir))
updateEnvironmentInput(ctx, cmd, args[0], state.GitInput(args[1], ref, subDir))
},
}

View File

@@ -3,7 +3,6 @@ package input
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/cmd/dagger/logger"
"go.dagger.io/dagger/state"
)
@@ -25,7 +24,7 @@ var jsonCmd = &cobra.Command{
updateEnvironmentInput(
ctx,
common.NewClient(ctx, false),
cmd,
args[0],
state.JSONInput(readInput(ctx, args[1])),
)

View File

@@ -40,6 +40,8 @@ var listCmd = &cobra.Command{
Str("environment", st.Name).
Logger()
doneCh := common.TrackWorkspaceCommand(ctx, cmd, workspace, st)
c, err := client.New(ctx, "", false)
if err != nil {
lg.Fatal().Err(err).Msg("unable to create client")
@@ -77,6 +79,8 @@ var listCmd = &cobra.Command{
return nil
})
<-doneCh
if err != nil {
lg.Fatal().Err(err).Msg("failed to query environment")
}

View File

@@ -8,11 +8,11 @@ import (
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.dagger.io/dagger/client"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/environment"
"go.dagger.io/dagger/solver"
"go.dagger.io/dagger/state"
"go.dagger.io/dagger/telemetry"
)
// Cmd exposes the top-level command
@@ -35,12 +35,23 @@ func init() {
)
}
func updateEnvironmentInput(ctx context.Context, cl *client.Client, target string, input state.Input) {
lg := log.Ctx(ctx)
func updateEnvironmentInput(ctx context.Context, cmd *cobra.Command, target string, input state.Input) {
lg := *log.Ctx(ctx)
workspace := common.CurrentWorkspace(ctx)
st := common.CurrentEnvironmentState(ctx, workspace)
lg = lg.With().
Str("environment", st.Name).
Logger()
doneCh := common.TrackWorkspaceCommand(ctx, cmd, workspace, st, &telemetry.Property{
Name: "input_target",
Value: target,
})
cl := common.NewClient(ctx, false)
st.SetInput(target, input)
err := cl.Do(ctx, st, func(ctx context.Context, env *environment.Environment, s solver.Solver) error {
@@ -52,12 +63,14 @@ func updateEnvironmentInput(ctx context.Context, cl *client.Client, target strin
return nil
})
<-doneCh
if err != nil {
lg.Fatal().Err(err).Str("environment", st.Name).Msg("invalid input")
lg.Fatal().Err(err).Msg("invalid input")
}
if err := workspace.Save(ctx, st); err != nil {
lg.Fatal().Err(err).Str("environment", st.Name).Msg("cannot update environment")
lg.Fatal().Err(err).Msg("cannot update environment")
}
}

View File

@@ -6,7 +6,6 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/cmd/dagger/logger"
"go.dagger.io/dagger/state"
"golang.org/x/term"
@@ -44,7 +43,7 @@ var secretCmd = &cobra.Command{
updateEnvironmentInput(
ctx,
common.NewClient(ctx, false),
cmd,
args[0],
state.SecretInput(secret),
)

View File

@@ -3,7 +3,6 @@ package input
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/cmd/dagger/logger"
"go.dagger.io/dagger/state"
)
@@ -25,7 +24,7 @@ var textCmd = &cobra.Command{
updateEnvironmentInput(
ctx,
common.NewClient(ctx, false),
cmd,
args[0],
state.TextInput(readInput(ctx, args[1])),
)

View File

@@ -3,7 +3,6 @@ package input
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.dagger.io/dagger/cmd/dagger/cmd/common"
"go.dagger.io/dagger/cmd/dagger/logger"
"go.dagger.io/dagger/state"
)
@@ -25,7 +24,7 @@ var yamlCmd = &cobra.Command{
updateEnvironmentInput(
ctx,
common.NewClient(ctx, false),
cmd,
args[0],
state.YAMLInput(readInput(ctx, args[1])),
)

View File

@@ -30,6 +30,8 @@ var listCmd = &cobra.Command{
ctx := lg.WithContext(cmd.Context())
workspace := common.CurrentWorkspace(ctx)
doneCh := common.TrackWorkspaceCommand(ctx, cmd, workspace, nil)
environments, err := workspace.List(ctx)
if err != nil {
lg.
@@ -44,6 +46,8 @@ var listCmd = &cobra.Command{
line := fmt.Sprintf("%s\t%s\t", e.Name, formatPath(e.Path))
fmt.Fprintln(w, line)
}
<-doneCh
},
}

View File

@@ -32,12 +32,15 @@ var newCmd = &cobra.Command{
}
name := args[0]
_, err := workspace.Create(ctx, name, state.Plan{
st, err := workspace.Create(ctx, name, state.Plan{
Package: viper.GetString("package"),
})
if err != nil {
lg.Fatal().Err(err).Msg("failed to create environment")
}
<-common.TrackWorkspaceCommand(ctx, cmd, workspace, st)
},
}

View File

@@ -34,11 +34,19 @@ var listCmd = &cobra.Command{
workspace := common.CurrentWorkspace(ctx)
st := common.CurrentEnvironmentState(ctx, workspace)
lg = lg.With().
Str("environment", st.Name).
Logger()
doneCh := common.TrackWorkspaceCommand(ctx, cmd, workspace, st)
cl := common.NewClient(ctx, false)
err := cl.Do(ctx, st, func(ctx context.Context, env *environment.Environment, s solver.Solver) error {
return ListOutputs(ctx, env, true)
})
<-doneCh
if err != nil {
lg.Fatal().Err(err).Msg("failed to scan outputs")
}

View File

@@ -30,8 +30,6 @@ var queryCmd = &cobra.Command{
lg := logger.New()
ctx := lg.WithContext(cmd.Context())
cueOpts := parseQueryFlags()
workspace := common.CurrentWorkspace(ctx)
state := common.CurrentEnvironmentState(ctx, workspace)
@@ -39,11 +37,14 @@ var queryCmd = &cobra.Command{
Str("environment", state.Name).
Logger()
cueOpts := parseQueryFlags()
cuePath := cue.MakePath()
if len(args) > 0 {
cuePath = cue.ParsePath(args[0])
}
doneCh := common.TrackWorkspaceCommand(ctx, cmd, workspace, state)
cl := common.NewClient(ctx, false)
cueVal := compiler.NewValue()
@@ -62,6 +63,8 @@ var queryCmd = &cobra.Command{
return nil
})
<-doneCh
if err != nil {
lg.Fatal().Err(err).Msg("failed to query environment")
}

View File

@@ -37,6 +37,12 @@ var upCmd = &cobra.Command{
workspace := common.CurrentWorkspace(ctx)
st := common.CurrentEnvironmentState(ctx, workspace)
lg = lg.With().
Str("environment", st.Name).
Logger()
doneCh := common.TrackWorkspaceCommand(ctx, cmd, workspace, st)
cl := common.NewClient(ctx, viper.GetBool("no-cache"))
err := cl.Do(ctx, st, func(ctx context.Context, env *environment.Environment, s solver.Solver) error {
@@ -57,6 +63,8 @@ var upCmd = &cobra.Command{
return output.ListOutputs(ctx, env, term.IsTerminal(int(os.Stdout.Fd())))
})
<-doneCh
if err != nil {
lg.Fatal().Err(err).Msg("failed to up environment")
}