From eef66f7fa518f21f7af24a8d820326de77aabe14 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Wed, 29 Nov 2023 14:40:09 -0800 Subject: [PATCH 01/42] New propto fields --- go/libraries/events/emitter.go | 4 +++- proto/dolt/services/eventsapi/v1alpha1/event_constants.proto | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 53b9bbcc12..cce62c2526 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -30,6 +30,8 @@ import ( "github.com/dolthub/dolt/go/libraries/utils/iohelp" ) +var Application = eventsapi.AppID_APP_DOLT + // Emitter is an interface used for processing a batch of events type Emitter interface { // LogEvents takes a batch of events and processes them @@ -110,7 +112,7 @@ func (em *GrpcEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) Version: version, Platform: plat, Events: evts, - App: eventsapi.AppID_APP_DOLT, + App: Application, } _, err := em.client.LogEvents(ctx, &req) diff --git a/proto/dolt/services/eventsapi/v1alpha1/event_constants.proto b/proto/dolt/services/eventsapi/v1alpha1/event_constants.proto index 51e6db7703..7138d083fb 100644 --- a/proto/dolt/services/eventsapi/v1alpha1/event_constants.proto +++ b/proto/dolt/services/eventsapi/v1alpha1/event_constants.proto @@ -92,6 +92,7 @@ enum ClientEventType { STASH_POP = 60; SHOW = 61; PROFILE = 62; + SQL_SERVER_HEARTBEAT = 63; } enum MetricID { @@ -110,4 +111,5 @@ enum AttributeID { enum AppID { APP_ID_UNSPECIFIED = 0; APP_DOLT = 1; + APP_DOLTGRES = 2; } From b0a97412d9cee7a91d01e70c3204537bcd6298ff Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Wed, 29 Nov 2023 14:41:23 -0800 Subject: [PATCH 02/42] Cleaner emit logic --- go/cmd/dolt/dolt.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 41b3ef5b28..30f9d41077 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -473,28 +473,19 @@ func runMain() int { emitter := events.NewFileEmitter(root, dbfactory.DoltDir) defer func() { - ces := events.GlobalCollector.Close() - // events.WriterEmitter{cli.CliOut}.LogEvents(Version, ces) - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") - disabled, err := strconv.ParseBool(metricsDisabled) - if err != nil { - // log.Print(err) + if err != nil || disabled { return } - if disabled { - return - } + ces := events.GlobalCollector.Close() // write events _ = emitter.LogEvents(Version, ces) // flush events - if err := processEventsDir(args, dEnv); err != nil { - // log.Print(err) - } + _ = processEventsDir(args, dEnv) }() if needsWriteAccess(subcommandName) { From 9d70fe7bf5a0120f076fa6c49bd3f5d205295e8b Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 14:37:33 -0800 Subject: [PATCH 03/42] Stop invoking a separate process to flush events --- go/cmd/dolt/commands/send_metrics.go | 39 ++++++++++++++-------------- go/cmd/dolt/dolt.go | 34 ++++++++++++------------ 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 3afbf0ffe7..6b7b6c988d 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -21,6 +21,7 @@ import ( "strconv" "time" + "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/fatih/color" "google.golang.org/grpc" @@ -82,7 +83,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st ap := cmd.ArgParser() - help, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{ShortDesc: sendMetricsShortDesc}, ap)) + help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{ShortDesc: sendMetricsShortDesc}, ap)) apr := cli.ParseArgsOrDie(ap, args, help) metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") @@ -102,25 +103,13 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() - root, err := dEnv.GetUserHomeDir() + userHomeDir, err := dEnv.GetUserHomeDir() if err != nil { - // log.Print(err) - return 1 + return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - dolt := dbfactory.DoltDir - - var flusher events.Flusher - - if apr.Contains(outputFlag) { - flusher = events.NewIOFlusher(dEnv.FS, root, dolt) - } else { - grpcEmitter := getGRPCEmitter(dEnv) - - flusher = events.NewGrpcEventFlusher(dEnv.FS, root, dolt, grpcEmitter) - } - - err = flusher.Flush(ctx) + outputToStdio := apr.Contains(outputFlag) + err = FlushEvents(ctx, dEnv, userHomeDir, outputToStdio) if err != nil { if err == events.ErrFileLocked { @@ -136,8 +125,20 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st return 1 } -// getGRPCEmitter gets the connection to the events grpc service -func getGRPCEmitter(dEnv *env.DoltEnv) *events.GrpcEmitter { +func FlushEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputToStdio bool) error { + var flusher events.Flusher + if outputToStdio { + flusher = events.NewIOFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir) + } else { + grpcEmitter := GRPCEventEmitterForEnv(dEnv) + flusher = events.NewGrpcEventFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, grpcEmitter) + } + + return flusher.Flush(ctx) +} + +// GRPCEventEmitterForEnv returns an event emitter for the given environment +func GRPCEventEmitterForEnv(dEnv *env.DoltEnv) *events.GrpcEmitter { host := dEnv.Config.GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) portStr := dEnv.Config.GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) insecureStr := dEnv.Config.GetStringOrDefault(env.MetricsInsecure, "false") diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 1901482635..2c1af5427e 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -480,7 +480,7 @@ func runMain() int { _ = emitter.LogEvents(Version, ces) // flush events - _ = processEventsDir(args, dEnv) + _ = processEventsDir(ctx, args, dEnv) }() if needsWriteAccess(subcommandName) { @@ -752,33 +752,35 @@ func seedGlobalRand() { } // processEventsDir runs the dolt send-metrics command in a new process -func processEventsDir(args []string, dEnv *env.DoltEnv) error { +func processEventsDir(ctx context.Context, args []string, dEnv *env.DoltEnv) error { if len(args) > 0 { - ignoreCommands := map[string]struct{}{ - commands.SendMetricsCommand: {}, - "init": {}, - "config": {}, - } - - _, ok := ignoreCommands[args[0]] - - if ok { + if !shouldFlushEvents(args[0]) { return nil } - - cmd := exec.Command("dolt", commands.SendMetricsCommand) - - if err := cmd.Start(); err != nil { - // log.Print(err) + + userHomeDir, err := dEnv.GetUserHomeDir() + if err != nil { return err } + // TODO: handle stdio output + _ = commands.FlushEvents(ctx, dEnv, userHomeDir, false) return nil } return nil } +func shouldFlushEvents(command string) bool { + ignoreCommands := map[string]struct{}{ + commands.SendMetricsCommand: {}, + "init": {}, + "config": {}, + } + _, ok := ignoreCommands[command] + return !ok +} + func interceptSendMetrics(ctx context.Context, args []string) (bool, int) { if len(args) < 1 || args[0] != commands.SendMetricsCommand { return false, 0 From e07983262a8c6d21d04ba5eae916aaee81ee9e5c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 14:55:52 -0800 Subject: [PATCH 04/42] Small cleanup --- go/cmd/dolt/commands/send_metrics.go | 5 +++-- go/cmd/dolt/dolt.go | 30 ++++++++++------------------ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 6b7b6c988d..1ca5107c8c 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -109,7 +109,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st } outputToStdio := apr.Contains(outputFlag) - err = FlushEvents(ctx, dEnv, userHomeDir, outputToStdio) + err = FlushLoggedEvents(ctx, dEnv, userHomeDir, outputToStdio) if err != nil { if err == events.ErrFileLocked { @@ -125,7 +125,8 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st return 1 } -func FlushEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputToStdio bool) error { +// FlushLoggedEvents flushes any logged events in the directory given to an appropriate event emitter +func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputToStdio bool) error { var flusher events.Flusher if outputToStdio { flusher = events.NewIOFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 2c1af5427e..fa9067f478 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -23,7 +23,6 @@ import ( "net/http" _ "net/http/pprof" "os" - "os/exec" "strconv" "time" @@ -437,7 +436,7 @@ func runMain() int { fs = filesys.LocalFS dEnv := env.Load(ctx, env.GetCurrentUserHomeDir, fs, doltdb.LocalDirDoltDB, Version) - root, err := env.GetCurrentUserHomeDir() + homeDir, err := env.GetCurrentUserHomeDir() if err != nil { cli.PrintErrln(color.RedString("Failed to load the HOME directory: %v", err)) return 1 @@ -464,9 +463,7 @@ func runMain() int { cli.PrintErrln(color.RedString("Failure to parse arguments: %v", err)) return 1 } - - emitter := events.NewFileEmitter(root, dbfactory.DoltDir) - + defer func() { metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) @@ -474,13 +471,14 @@ func runMain() int { return } - ces := events.GlobalCollector.Close() - // write events - _ = emitter.LogEvents(Version, ces) + emitter := events.NewFileEmitter(homeDir, dbfactory.DoltDir) + _ = emitter.LogEvents(Version, events.GlobalCollector.Close()) // flush events - _ = processEventsDir(ctx, args, dEnv) + if len(args) > 0 && shouldFlushEvents(args[0]) { + _ = processEventsDir(ctx, dEnv) + } }() if needsWriteAccess(subcommandName) { @@ -751,24 +749,16 @@ func seedGlobalRand() { rand.Seed(int64(binary.LittleEndian.Uint64(bs))) } -// processEventsDir runs the dolt send-metrics command in a new process -func processEventsDir(ctx context.Context, args []string, dEnv *env.DoltEnv) error { - if len(args) > 0 { - if !shouldFlushEvents(args[0]) { - return nil - } - +// processEventsDir flushes all logged events to an appropriate event emitter (typically a gRPC client). +func processEventsDir(ctx context.Context, dEnv *env.DoltEnv) error { userHomeDir, err := dEnv.GetUserHomeDir() if err != nil { return err } // TODO: handle stdio output - _ = commands.FlushEvents(ctx, dEnv, userHomeDir, false) + _ = commands.FlushLoggedEvents(ctx, dEnv, userHomeDir, false) return nil - } - - return nil } func shouldFlushEvents(command string) bool { From 47f34b2b1feae4d6fe29ff02c227b8b7e7bb72aa Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 15:05:07 -0800 Subject: [PATCH 05/42] Removed hard-coded dolt ref --- go/libraries/events/file_backed_proc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/events/file_backed_proc.go b/go/libraries/events/file_backed_proc.go index a75ae2df7d..2f4164b2ae 100644 --- a/go/libraries/events/file_backed_proc.go +++ b/go/libraries/events/file_backed_proc.go @@ -210,7 +210,7 @@ func (fbp *FileBackedProc) WriteEvents(version string, evts []*eventsapi.ClientE Version: version, Platform: plat, Events: evts, - App: eventsapi.AppID_APP_DOLT, + App: Application, } data, err := proto.Marshal(req) From be31b2852e2b8c62acd1ecce99a16fc5843bdd17 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Fri, 1 Dec 2023 15:28:56 -0800 Subject: [PATCH 06/42] adds --single-branch for dolt clone --- go/cmd/dolt/cli/arg_parser_helpers.go | 1 + go/cmd/dolt/cli/flags.go | 1 + go/cmd/dolt/commands/clone.go | 3 +- go/libraries/doltcore/env/actions/clone.go | 30 +++++++++---------- .../doltcore/sqle/database_provider.go | 2 +- integration-tests/bats/remotes.bats | 15 ++++++++++ 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/go/cmd/dolt/cli/arg_parser_helpers.go b/go/cmd/dolt/cli/arg_parser_helpers.go index 9848beb391..eb8cd1ae06 100644 --- a/go/cmd/dolt/cli/arg_parser_helpers.go +++ b/go/cmd/dolt/cli/arg_parser_helpers.go @@ -125,6 +125,7 @@ func CreateCloneArgParser() *argparser.ArgParser { ap.SupportsString(dbfactory.OSSCredsFileParam, "", "file", "OSS credentials file.") ap.SupportsString(dbfactory.OSSCredsProfile, "", "profile", "OSS profile to use.") ap.SupportsString(UserFlag, "u", "user", "User name to use when authenticating with the remote. Gets password from the environment variable {{.EmphasisLeft}}DOLT_REMOTE_PASSWORD{{.EmphasisRight}}.") + ap.SupportsFlag(SingleBranchFlag, "", "Clone only the history leading to the tip of a single branch, either specified by --branch or the primary branch remote's HEAD points at.") return ap } diff --git a/go/cmd/dolt/cli/flags.go b/go/cmd/dolt/cli/flags.go index 0a411ddc03..1fdaa1b013 100644 --- a/go/cmd/dolt/cli/flags.go +++ b/go/cmd/dolt/cli/flags.go @@ -59,6 +59,7 @@ const ( ShallowFlag = "shallow" ShowIgnoredFlag = "ignored" SilentFlag = "silent" + SingleBranchFlag = "single-branch" SkipEmptyFlag = "skip-empty" SoftResetParam = "soft" SquashParam = "squash" diff --git a/go/cmd/dolt/commands/clone.go b/go/cmd/dolt/commands/clone.go index 5768563401..2940f2fa48 100644 --- a/go/cmd/dolt/commands/clone.go +++ b/go/cmd/dolt/commands/clone.go @@ -98,6 +98,7 @@ func (cmd CloneCmd) Exec(ctx context.Context, commandStr string, args []string, func clone(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv) errhand.VerboseError { remoteName := apr.GetValueOrDefault(cli.RemoteParam, "origin") branch := apr.GetValueOrDefault(cli.BranchParam, "") + singleBranch := apr.Contains(cli.SingleBranchFlag) dir, urlStr, verr := parseArgs(apr) if verr != nil { return verr @@ -143,7 +144,7 @@ func clone(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEn // Nil out the old Dolt env so we don't accidentally operate on the wrong database dEnv = nil - err = actions.CloneRemote(ctx, srcDB, remoteName, branch, clonedEnv) + err = actions.CloneRemote(ctx, srcDB, remoteName, branch, singleBranch, clonedEnv) if err != nil { // If we're cloning into a directory that already exists do not erase it. Otherwise // make best effort to delete the directory we created. diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index f24abd5142..82d5de273a 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -156,7 +156,7 @@ func sortedKeys(m map[string]iohelp.ReadStats) []string { return keys } -func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch string, dEnv *env.DoltEnv) error { +func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch string, singleBranch bool, dEnv *env.DoltEnv) error { eventCh := make(chan pull.TableFileEvent, 128) wg := &sync.WaitGroup{} @@ -215,25 +215,25 @@ func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch s // create remote refs corresponding to each of them. We delete all of // the local branches except for the one corresponding to |branch|. for _, brnch := range branches { - cs, _ := doltdb.NewCommitSpec(brnch.GetPath()) - cm, err := dEnv.DoltDB.Resolve(ctx, cs, nil) - if err != nil { - return fmt.Errorf("%w: %s; %s", ErrFailedToResolveBranchRef, brnch.String(), err.Error()) - - } - - remoteRef := ref.NewRemoteRef(remoteName, brnch.GetPath()) - err = dEnv.DoltDB.SetHeadToCommit(ctx, remoteRef, cm) - if err != nil { - return fmt.Errorf("%w: %s; %s", ErrFailedToCreateRemoteRef, remoteRef.String(), err.Error()) - - } - if brnch.GetPath() != branch { err := dEnv.DoltDB.DeleteBranch(ctx, brnch, nil) if err != nil { return fmt.Errorf("%w: %s; %s", ErrFailedToDeleteBranch, brnch.String(), err.Error()) } + } else if !singleBranch || brnch.GetPath() == branch { + cs, _ := doltdb.NewCommitSpec(brnch.GetPath()) + cm, err := dEnv.DoltDB.Resolve(ctx, cs, nil) + if err != nil { + return fmt.Errorf("%w: %s; %s", ErrFailedToResolveBranchRef, brnch.String(), err.Error()) + + } + + remoteRef := ref.NewRemoteRef(remoteName, brnch.GetPath()) + err = dEnv.DoltDB.SetHeadToCommit(ctx, remoteRef, cm) + if err != nil { + return fmt.Errorf("%w: %s; %s", ErrFailedToCreateRemoteRef, remoteRef.String(), err.Error()) + + } } } diff --git a/go/libraries/doltcore/sqle/database_provider.go b/go/libraries/doltcore/sqle/database_provider.go index 4113578600..5ff4c1af57 100644 --- a/go/libraries/doltcore/sqle/database_provider.go +++ b/go/libraries/doltcore/sqle/database_provider.go @@ -527,7 +527,7 @@ func (p *DoltDatabaseProvider) cloneDatabaseFromRemote( return nil, err } - err = actions.CloneRemote(ctx, srcDB, remoteName, branch, dEnv) + err = actions.CloneRemote(ctx, srcDB, remoteName, branch, false, dEnv) if err != nil { return nil, err } diff --git a/integration-tests/bats/remotes.bats b/integration-tests/bats/remotes.bats index 76698efc6d..0dd65d7d5e 100644 --- a/integration-tests/bats/remotes.bats +++ b/integration-tests/bats/remotes.bats @@ -1008,6 +1008,21 @@ create_five_remote_branches_main_and_master() { [[ "$output" =~ "remotes/origin/branch-two" ]] || false } +@test "remotes: clone --single-branch does not create remote refs for all remote branches" { + create_three_remote_branches + cd dolt-repo-clones + dolt clone --single-branch http://localhost:50051/test-org/test-repo + cd test-repo + run dolt branch -a + [ "$status" -eq 0 ] + [[ "$output" =~ "* main" ]] || false + [[ ! "$output" =~ " branch-one" ]] || false + [[ ! "$output" =~ " branch-two" ]] || false + [[ "$output" =~ "remotes/origin/main" ]] || false + [[ ! "$output" =~ "remotes/origin/branch-one" ]] || false + [[ ! "$output" =~ "remotes/origin/branch-two" ]] || false +} + @test "remotes: fetch creates new remote refs for new remote branches" { create_main_remote_branch From 90b62c8bd75a5c1cc05e2d9d0c4a44caf0912345 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Fri, 1 Dec 2023 15:51:44 -0800 Subject: [PATCH 07/42] small fix --- go/libraries/doltcore/dtestutils/testcommands/multienv.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/doltcore/dtestutils/testcommands/multienv.go b/go/libraries/doltcore/dtestutils/testcommands/multienv.go index ecb6ba4db1..f5ac33a219 100644 --- a/go/libraries/doltcore/dtestutils/testcommands/multienv.go +++ b/go/libraries/doltcore/dtestutils/testcommands/multienv.go @@ -195,7 +195,7 @@ func (mr *MultiRepoTestSetup) CloneDB(fromRemote, dbName string) { mr.Errhand(err) } - err = actions.CloneRemote(ctx, srcDB, r.Name, "", dEnv) + err = actions.CloneRemote(ctx, srcDB, r.Name, "", false, dEnv) if err != nil { mr.Errhand(err) } From 4276eb6f0fef2c088f6e7181380799811f9fce23 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 16:11:48 -0800 Subject: [PATCH 08/42] New proto gen --- go/cmd/dolt/commands/sqlserver/server.go | 44 ++++++++++++++ .../eventsapi/v1alpha1/client_event.pb.go | 5 +- .../v1alpha1/client_event_grpc.pb.go | 1 - .../eventsapi/v1alpha1/event_constants.pb.go | 57 +++++++++++-------- .../remotesapi/v1alpha1/chunkstore.pb.go | 5 +- .../remotesapi/v1alpha1/chunkstore_grpc.pb.go | 1 - .../remotesapi/v1alpha1/credentials.pb.go | 5 +- .../v1alpha1/credentials_grpc.pb.go | 1 - .../replicationapi/v1alpha1/replication.pb.go | 5 +- .../v1alpha1/replication_grpc.pb.go | 1 - 10 files changed, 84 insertions(+), 41 deletions(-) diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index c4f771f261..d381356c9c 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,6 +26,8 @@ import ( "strings" "time" + eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" + "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -123,6 +125,11 @@ func Serve( }, } controller.Register(InitLogging) + + emitHeartbeat := &heartbeatService{ + dEnv: dEnv, + } + controller.Register(emitHeartbeat) fs := dEnv.FS InitDataDir := &svcs.AnonService{ @@ -561,6 +568,43 @@ func Serve( return nil, controller.WaitForStop() } +type heartbeatService struct { + dEnv *env.DoltEnv + eventEmitter *events.GrpcEmitter +} + +func (h *heartbeatService) Init(ctx context.Context) error { + h.eventEmitter = commands.GRPCEventEmitterForEnv(h.dEnv) + return nil +} + +func (h *heartbeatService) Stop() error {return nil} + +func (h *heartbeatService) Run(ctx context.Context) { + ticker := time.NewTicker(24 * time.Hour) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + h.eventEmitter.LogEvents("TODO", []*eventsapi.ClientEvent{ + { + Id: "", + StartTime: nil, + EndTime: nil, + Type: eventsapi.ClientEventType_SQL_SERVER_HEARTBEAT, + Attributes: nil, + Metrics: nil, + }, + }) + } + } +} + +var _ svcs.Service = &heartbeatService{} + func persistServerLocalCreds(port int, dEnv *env.DoltEnv) (*LocalCreds, error) { creds := NewLocalCreds(port) err := WriteLocalCreds(dEnv.FS, creds) diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go index 6e09d77b48..50e349ba74 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go @@ -23,13 +23,12 @@ package eventsapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go index 8a09ad1cf6..085a9fda2b 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go @@ -24,7 +24,6 @@ package eventsapi import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go index 188068cfc1..233ed21896 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go @@ -23,11 +23,10 @@ package eventsapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( @@ -155,6 +154,7 @@ const ( ClientEventType_STASH_POP ClientEventType = 60 ClientEventType_SHOW ClientEventType = 61 ClientEventType_PROFILE ClientEventType = 62 + ClientEventType_SQL_SERVER_HEARTBEAT ClientEventType = 63 ) // Enum value maps for ClientEventType. @@ -223,6 +223,7 @@ var ( 60: "STASH_POP", 61: "SHOW", 62: "PROFILE", + 63: "SQL_SERVER_HEARTBEAT", } ClientEventType_value = map[string]int32{ "TYPE_UNSPECIFIED": 0, @@ -288,6 +289,7 @@ var ( "STASH_POP": 60, "SHOW": 61, "PROFILE": 62, + "SQL_SERVER_HEARTBEAT": 63, } ) @@ -421,6 +423,7 @@ type AppID int32 const ( AppID_APP_ID_UNSPECIFIED AppID = 0 AppID_APP_DOLT AppID = 1 + AppID_APP_DOLTGRES AppID = 2 ) // Enum value maps for AppID. @@ -428,10 +431,12 @@ var ( AppID_name = map[int32]string{ 0: "APP_ID_UNSPECIFIED", 1: "APP_DOLT", + 2: "APP_DOLTGRES", } AppID_value = map[string]int32{ "APP_ID_UNSPECIFIED": 0, "APP_DOLT": 1, + "APP_DOLTGRES": 2, } ) @@ -475,7 +480,7 @@ var file_dolt_services_eventsapi_v1alpha1_event_constants_proto_rawDesc = []byte 0x52, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x53, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x41, 0x52, 0x57, - 0x49, 0x4e, 0x10, 0x03, 0x2a, 0xfd, 0x07, 0x0a, 0x0f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, + 0x49, 0x4e, 0x10, 0x03, 0x2a, 0x97, 0x08, 0x0a, 0x0f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, @@ -539,27 +544,29 @@ var file_dolt_services_eventsapi_v1alpha1_event_constants_proto_rawDesc = []byte 0x0a, 0x0a, 0x53, 0x54, 0x41, 0x53, 0x48, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x3b, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x54, 0x41, 0x53, 0x48, 0x5f, 0x50, 0x4f, 0x50, 0x10, 0x3c, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x48, 0x4f, 0x57, 0x10, 0x3d, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f, 0x46, 0x49, - 0x4c, 0x45, 0x10, 0x3e, 0x2a, 0x6a, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x49, 0x44, - 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x59, 0x54, 0x45, - 0x53, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, - 0x0a, 0x13, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x4d, 0x53, 0x5f, 0x45, 0x4c, - 0x41, 0x50, 0x53, 0x45, 0x44, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x4d, 0x4f, 0x54, - 0x45, 0x41, 0x50, 0x49, 0x5f, 0x52, 0x50, 0x43, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, - 0x2a, 0x45, 0x0a, 0x0b, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x44, 0x12, - 0x19, 0x0a, 0x15, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, - 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x55, 0x52, 0x4c, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x45, 0x10, - 0x02, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, 0x2a, 0x2d, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, 0x44, - 0x12, 0x16, 0x0a, 0x12, 0x41, 0x50, 0x50, 0x5f, 0x49, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x50, 0x50, 0x5f, - 0x44, 0x4f, 0x4c, 0x54, 0x10, 0x01, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x6c, 0x74, 0x68, 0x75, 0x62, 0x2f, 0x64, 0x6f, 0x6c, - 0x74, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, - 0x6f, 0x6c, 0x74, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x4c, 0x45, 0x10, 0x3e, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x51, 0x4c, 0x5f, 0x53, 0x45, 0x52, 0x56, + 0x45, 0x52, 0x5f, 0x48, 0x45, 0x41, 0x52, 0x54, 0x42, 0x45, 0x41, 0x54, 0x10, 0x3f, 0x2a, 0x6a, + 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, + 0x54, 0x52, 0x49, 0x43, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x59, 0x54, 0x45, 0x53, 0x5f, 0x44, 0x4f, 0x57, 0x4e, + 0x4c, 0x4f, 0x41, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x4f, 0x57, 0x4e, + 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x4d, 0x53, 0x5f, 0x45, 0x4c, 0x41, 0x50, 0x53, 0x45, 0x44, 0x10, + 0x02, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x41, 0x50, 0x49, 0x5f, 0x52, + 0x50, 0x43, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x2a, 0x45, 0x0a, 0x0b, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x44, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x54, 0x54, + 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x55, + 0x52, 0x4c, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x45, 0x10, 0x02, 0x22, 0x04, 0x08, 0x01, 0x10, + 0x01, 0x2a, 0x3f, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x50, + 0x50, 0x5f, 0x49, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x50, 0x50, 0x5f, 0x44, 0x4f, 0x4c, 0x54, 0x10, 0x01, + 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x50, 0x50, 0x5f, 0x44, 0x4f, 0x4c, 0x54, 0x47, 0x52, 0x45, 0x53, + 0x10, 0x02, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x64, 0x6f, 0x6c, 0x74, 0x68, 0x75, 0x62, 0x2f, 0x64, 0x6f, 0x6c, 0x74, 0x2f, 0x67, 0x6f, + 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x6f, 0x6c, 0x74, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x61, + 0x70, 0x69, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go index dde8ed815b..0fc8ae7e15 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go @@ -21,12 +21,11 @@ package remotesapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go index 28cfc20104..828da30d62 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go @@ -22,7 +22,6 @@ package remotesapi import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go index 7c2e689b33..8164b2bb9a 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go @@ -21,11 +21,10 @@ package remotesapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go index 8ae0dfc1eb..e859388139 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go @@ -22,7 +22,6 @@ package remotesapi import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go index 6ac797942a..c0dd217790 100644 --- a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go +++ b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go @@ -21,11 +21,10 @@ package replicationapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go index 275cc34a39..3af833933d 100644 --- a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go +++ b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go @@ -22,7 +22,6 @@ package replicationapi import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" From 7b2768c79cd58bfb97a3ad0e8c21a438b64cfd89 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 16:13:42 -0800 Subject: [PATCH 09/42] Formatting --- go/cmd/dolt/commands/send_metrics.go | 2 +- go/cmd/dolt/commands/sqlserver/server.go | 10 +++++----- go/cmd/dolt/dolt.go | 20 +++++++++---------- .../eventsapi/v1alpha1/client_event.pb.go | 5 +++-- .../v1alpha1/client_event_grpc.pb.go | 1 + .../eventsapi/v1alpha1/event_constants.pb.go | 5 +++-- .../remotesapi/v1alpha1/chunkstore.pb.go | 5 +++-- .../remotesapi/v1alpha1/chunkstore_grpc.pb.go | 1 + .../remotesapi/v1alpha1/credentials.pb.go | 5 +++-- .../v1alpha1/credentials_grpc.pb.go | 1 + .../replicationapi/v1alpha1/replication.pb.go | 5 +++-- .../v1alpha1/replication_grpc.pb.go | 1 + 12 files changed, 35 insertions(+), 26 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 1ca5107c8c..8229925e15 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -21,11 +21,11 @@ import ( "strconv" "time" - "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/fatih/color" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" + "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index d381356c9c..82ffc2b687 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,8 +26,6 @@ import ( "strings" "time" - eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" - "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -42,6 +40,7 @@ import ( "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/commands" "github.com/dolthub/dolt/go/cmd/dolt/commands/engine" + eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/remotesrv" "github.com/dolthub/dolt/go/libraries/doltcore/sqle" @@ -50,6 +49,7 @@ import ( _ "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" "github.com/dolthub/dolt/go/libraries/doltcore/sqlserver" + "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/svcs" ) @@ -125,7 +125,7 @@ func Serve( }, } controller.Register(InitLogging) - + emitHeartbeat := &heartbeatService{ dEnv: dEnv, } @@ -569,7 +569,7 @@ func Serve( } type heartbeatService struct { - dEnv *env.DoltEnv + dEnv *env.DoltEnv eventEmitter *events.GrpcEmitter } @@ -578,7 +578,7 @@ func (h *heartbeatService) Init(ctx context.Context) error { return nil } -func (h *heartbeatService) Stop() error {return nil} +func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { ticker := time.NewTicker(24 * time.Hour) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index fa9067f478..33d12c7269 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -463,7 +463,7 @@ func runMain() int { cli.PrintErrln(color.RedString("Failure to parse arguments: %v", err)) return 1 } - + defer func() { metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) @@ -749,16 +749,16 @@ func seedGlobalRand() { rand.Seed(int64(binary.LittleEndian.Uint64(bs))) } -// processEventsDir flushes all logged events to an appropriate event emitter (typically a gRPC client). -func processEventsDir(ctx context.Context, dEnv *env.DoltEnv) error { - userHomeDir, err := dEnv.GetUserHomeDir() - if err != nil { - return err - } +// processEventsDir flushes all logged events to an appropriate event emitter (typically a gRPC client). +func processEventsDir(ctx context.Context, dEnv *env.DoltEnv) error { + userHomeDir, err := dEnv.GetUserHomeDir() + if err != nil { + return err + } - // TODO: handle stdio output - _ = commands.FlushLoggedEvents(ctx, dEnv, userHomeDir, false) - return nil + // TODO: handle stdio output + _ = commands.FlushLoggedEvents(ctx, dEnv, userHomeDir, false) + return nil } func shouldFlushEvents(command string) bool { diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go index 50e349ba74..6e09d77b48 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go @@ -23,12 +23,13 @@ package eventsapi import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go index 085a9fda2b..8a09ad1cf6 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go @@ -24,6 +24,7 @@ package eventsapi import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go index 233ed21896..a3e22c7a62 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go @@ -23,10 +23,11 @@ package eventsapi import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go index 0fc8ae7e15..dde8ed815b 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go @@ -21,11 +21,12 @@ package remotesapi import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go index 828da30d62..28cfc20104 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go @@ -22,6 +22,7 @@ package remotesapi import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go index 8164b2bb9a..7c2e689b33 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go @@ -21,10 +21,11 @@ package remotesapi import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go index e859388139..8ae0dfc1eb 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go @@ -22,6 +22,7 @@ package remotesapi import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go index c0dd217790..6ac797942a 100644 --- a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go +++ b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go @@ -21,10 +21,11 @@ package replicationapi import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go index 3af833933d..275cc34a39 100644 --- a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go +++ b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go @@ -22,6 +22,7 @@ package replicationapi import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" From 124967af38e44cd8d7f2d0c3f3f7e9dafafe0d89 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 17:11:25 -0800 Subject: [PATCH 10/42] SQL server heartbeater --- go/cmd/dolt/commands/send_metrics.go | 51 +++++++++++++----------- go/cmd/dolt/commands/sqlserver/server.go | 39 +++++++++++------- go/libraries/events/events.go | 6 +-- 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 8229925e15..1319f6eb01 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -17,7 +17,6 @@ package commands import ( "context" "fmt" - "log" "strconv" "time" @@ -138,36 +137,40 @@ func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir strin return flusher.Flush(ctx) } -// GRPCEventEmitterForEnv returns an event emitter for the given environment +// GRPCEventEmitterForEnv returns an event emitter for the given environment, or nil if the environment cannot +// provide one func GRPCEventEmitterForEnv(dEnv *env.DoltEnv) *events.GrpcEmitter { - host := dEnv.Config.GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) - portStr := dEnv.Config.GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) - insecureStr := dEnv.Config.GetStringOrDefault(env.MetricsInsecure, "false") - - port, err := strconv.ParseUint(portStr, 10, 16) - - if err != nil { - log.Println(color.YellowString("The config value of '%s' is '%s' which is not a valid port.", env.MetricsPort, portStr)) - return nil - } - - insecure, err := strconv.ParseBool(insecureStr) - - if err != nil { - log.Println(color.YellowString("The config value of '%s' is '%s' which is not a valid true/false value", env.MetricsInsecure, insecureStr)) - } - - hostAndPort := fmt.Sprintf("%s:%d", host, port) - cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ - Endpoint: hostAndPort, - Insecure: insecure, - }) + cfg, err := GRPCEventRemoteConfigForEnv(dEnv) if err != nil { return nil } + conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) if err != nil { return nil } return events.NewGrpcEmitter(conn) } + +func GRPCEventRemoteConfigForEnv(dEnv *env.DoltEnv) (dbfactory.GRPCRemoteConfig, error) { + host := dEnv.Config.GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) + portStr := dEnv.Config.GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) + insecureStr := dEnv.Config.GetStringOrDefault(env.MetricsInsecure, "false") + + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + insecure, _ := strconv.ParseBool(insecureStr) + + hostAndPort := fmt.Sprintf("%s:%d", host, port) + cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ + Endpoint: hostAndPort, + Insecure: insecure, + }) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + return cfg, err +} diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 82ffc2b687..7f7e29d966 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,6 +26,7 @@ import ( "strings" "time" + "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -33,8 +34,10 @@ import ( "github.com/dolthub/go-mysql-server/sql/plan" "github.com/dolthub/go-mysql-server/sql/types" "github.com/dolthub/vitess/go/mysql" + "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/sirupsen/logrus" + "google.golang.org/grpc" goerrors "gopkg.in/src-d/go-errors.v1" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -126,9 +129,7 @@ func Serve( } controller.Register(InitLogging) - emitHeartbeat := &heartbeatService{ - dEnv: dEnv, - } + emitHeartbeat := newHeartbeatService(version, dEnv) controller.Register(emitHeartbeat) fs := dEnv.FS @@ -569,16 +570,17 @@ func Serve( } type heartbeatService struct { - dEnv *env.DoltEnv - eventEmitter *events.GrpcEmitter + version string + cfg dbfactory.GRPCRemoteConfig } -func (h *heartbeatService) Init(ctx context.Context) error { - h.eventEmitter = commands.GRPCEventEmitterForEnv(h.dEnv) - return nil +func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { + cfg, _ := commands.GRPCEventRemoteConfigForEnv(dEnv) + return &heartbeatService{version: version, cfg: cfg} } -func (h *heartbeatService) Stop() error { return nil } +func (h *heartbeatService) Init(ctx context.Context) error { return nil } +func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { ticker := time.NewTicker(24 * time.Hour) @@ -589,16 +591,23 @@ func (h *heartbeatService) Run(ctx context.Context) { case <-ctx.Done(): return case <-ticker.C: - h.eventEmitter.LogEvents("TODO", []*eventsapi.ClientEvent{ + conn, err := grpc.Dial(h.cfg.Endpoint, h.cfg.DialOptions...) + if err != nil { + continue + } + + eventEmitter := events.NewGrpcEmitter(conn) + t := events.NowTimestamp() + _ = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ { - Id: "", - StartTime: nil, - EndTime: nil, + Id: uuid.New().String(), + StartTime: t, + EndTime: t, Type: eventsapi.ClientEventType_SQL_SERVER_HEARTBEAT, - Attributes: nil, - Metrics: nil, }, }) + + _ = conn.Close() } } } diff --git a/go/libraries/events/events.go b/go/libraries/events/events.go index 2a98096eb4..723e1aec40 100644 --- a/go/libraries/events/events.go +++ b/go/libraries/events/events.go @@ -27,7 +27,7 @@ import ( // EventNowFunc function is used to get the current time and can be overridden for testing. var EventNowFunc = time.Now -func nowTimestamp() *timestamppb.Timestamp { +func NowTimestamp() *timestamppb.Timestamp { now := EventNowFunc() ts := timestamppb.New(now) err := ts.CheckValid() @@ -51,7 +51,7 @@ func NewEvent(ceType eventsapi.ClientEventType) *Event { return &Event{ ce: &eventsapi.ClientEvent{ Id: uuid.New().String(), - StartTime: nowTimestamp(), + StartTime: NowTimestamp(), Type: ceType, }, m: &sync.Mutex{}, @@ -83,7 +83,7 @@ func (evt *Event) close() *eventsapi.ClientEvent { evt.m.Lock() defer evt.m.Unlock() - evt.ce.EndTime = nowTimestamp() + evt.ce.EndTime = NowTimestamp() for k, v := range evt.attributes { evt.ce.Attributes = append(evt.ce.Attributes, &eventsapi.ClientEventAttribute{Id: k, Value: v}) From bca9aff6423d00ec30e40cadd13a08f2f9c98458 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 17:29:49 -0800 Subject: [PATCH 11/42] Revert to previous behavior of invoking the send metrics command --- go/cmd/dolt/dolt.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 33d12c7269..9739a47345 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -23,6 +23,8 @@ import ( "net/http" _ "net/http/pprof" "os" + "os/exec" + "path/filepath" "strconv" "time" @@ -477,7 +479,7 @@ func runMain() int { // flush events if len(args) > 0 && shouldFlushEvents(args[0]) { - _ = processEventsDir(ctx, dEnv) + _ = processEventsDir() } }() @@ -749,15 +751,25 @@ func seedGlobalRand() { rand.Seed(int64(binary.LittleEndian.Uint64(bs))) } -// processEventsDir flushes all logged events to an appropriate event emitter (typically a gRPC client). -func processEventsDir(ctx context.Context, dEnv *env.DoltEnv) error { - userHomeDir, err := dEnv.GetUserHomeDir() +// processEventsDir flushes all logged events in a separate process. +// This is done without blocking so that the main process can exit immediately in the case of a slow network. +func processEventsDir() error { + path, err := os.Executable() if err != nil { return err } - // TODO: handle stdio output - _ = commands.FlushLoggedEvents(ctx, dEnv, userHomeDir, false) + absPath, err := filepath.Abs(path) + if err != nil { + return err + } + + cmd := exec.Command(absPath, commands.SendMetricsCommand) + + if err := cmd.Start(); err != nil { + return err + } + return nil } From de38dcce475302ce5da1c03401c973c2def9b099 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 17:42:22 -0800 Subject: [PATCH 12/42] Cleanup --- go/cmd/dolt/commands/sqlserver/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 7f7e29d966..b90f31a1b1 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -129,8 +129,7 @@ func Serve( } controller.Register(InitLogging) - emitHeartbeat := newHeartbeatService(version, dEnv) - controller.Register(emitHeartbeat) + controller.Register(newHeartbeatService(version, dEnv)) fs := dEnv.FS InitDataDir := &svcs.AnonService{ @@ -569,6 +568,7 @@ func Serve( return nil, controller.WaitForStop() } +// heartbeatService is a service that sends a heartbeat event to the metrics server once a day type heartbeatService struct { version string cfg dbfactory.GRPCRemoteConfig From d31758468d06837efb0f69e335130e29567cb168 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 17:44:27 -0800 Subject: [PATCH 13/42] go mod cleanup --- go/go.mod | 14 +++++++------- go/go.sum | 17 ++++++++--------- integration-tests/go-sql-server-driver/go.mod | 2 +- integration-tests/go-sql-server-driver/go.sum | 11 ++--------- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/go/go.mod b/go/go.mod index ff7c300a18..3f0bd990c9 100644 --- a/go/go.mod +++ b/go/go.mod @@ -16,17 +16,16 @@ require ( github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488 github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f - github.com/dustin/go-humanize v1.0.0 + github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.13.0 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/go-sql-driver/mysql v1.7.2-0.20230713085235-0b18dac46f7f github.com/gocraft/dbr/v2 v2.7.2 - github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 github.com/google/uuid v1.3.0 github.com/jpillora/backoff v1.0.0 github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d - github.com/mattn/go-isatty v0.0.16 + github.com/mattn/go-isatty v0.0.17 github.com/mattn/go-runewidth v0.0.13 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.5.0 @@ -36,9 +35,8 @@ require ( github.com/silvasur/buzhash v0.0.0-20160816060738-9bdec3dec7c6 github.com/sirupsen/logrus v1.8.1 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 github.com/tealeg/xlsx v1.0.5 - github.com/tklauser/go-sysconf v0.3.9 // indirect go.uber.org/zap v1.24.0 golang.org/x/crypto v0.14.0 golang.org/x/net v0.17.0 @@ -114,6 +112,7 @@ require ( github.com/go-pdf/fpdf v0.6.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/s2a-go v0.1.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect @@ -121,7 +120,7 @@ require ( github.com/gorilla/mux v1.8.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.10.10 // indirect + github.com/klauspost/compress v1.10.5 // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect github.com/lestrrat-go/strftime v1.0.4 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect @@ -138,6 +137,7 @@ require ( github.com/tetratelabs/wazero v1.1.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect + github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/tklauser/numcpus v0.3.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.opencensus.io v0.24.0 // indirect @@ -147,7 +147,7 @@ require ( golang.org/x/mod v0.12.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect golang.org/x/term v0.13.0 // indirect - golang.org/x/time v0.1.0 // indirect + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect golang.org/x/tools v0.13.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go/go.sum b/go/go.sum index cf1ad94a2b..131c69cfb9 100644 --- a/go/go.sum +++ b/go/go.sum @@ -196,8 +196,8 @@ github.com/dolthub/swiss v0.1.0/go.mod h1:BeucyB08Vb1G9tumVN3Vp/pyY4AMUnr9p7Rz7w github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f h1:I480LKHhb4usnF3dYhp6J4ORKMrncNKaWYZvIZwlK+U= github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f/go.mod h1:IwjNXSQPymrja5pVqmfnYdcy7Uv7eNJNBPK/MEh9OOw= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= @@ -432,9 +432,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.5 h1:7q6vHIqubShURwQz8cQK6yIe/xC3IF0Vm7TGfqjewrc= github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I= -github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -476,8 +475,9 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -648,8 +648,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE= github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= github.com/tetratelabs/wazero v1.1.0 h1:EByoAhC+QcYpwSZJSs/aV0uokxPwBgKxfiokSUwAknQ= @@ -961,9 +961,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/integration-tests/go-sql-server-driver/go.mod b/integration-tests/go-sql-server-driver/go.mod index f9f6e54012..cd31fd8d09 100644 --- a/integration-tests/go-sql-server-driver/go.mod +++ b/integration-tests/go-sql-server-driver/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/dolthub/dolt/go v0.40.4 github.com/google/uuid v1.3.0 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 golang.org/x/sync v0.3.0 gopkg.in/square/go-jose.v2 v2.5.1 gopkg.in/yaml.v3 v3.0.1 diff --git a/integration-tests/go-sql-server-driver/go.sum b/integration-tests/go-sql-server-driver/go.sum index 07862eae62..f088962fe0 100644 --- a/integration-tests/go-sql-server-driver/go.sum +++ b/integration-tests/go-sql-server-driver/go.sum @@ -1,6 +1,5 @@ github.com/creasty/defaults v1.6.0 h1:ltuE9cfphUtlrBeomuu8PEyISTXnxqkBIoQfXgv7BSc= github.com/creasty/defaults v1.6.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-sql-driver/mysql v1.7.2-0.20230713085235-0b18dac46f7f h1:4+t8Qb99xUG/Ea00cQAiQl+gsjpK8ZYtAO8E76gRzQI= @@ -11,13 +10,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= @@ -28,6 +22,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From f63ad7b1a4d0d37db33f7e4b8041edd8526c52a6 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 18:03:18 -0800 Subject: [PATCH 14/42] Added check for disabled metrics --- go/cmd/dolt/commands/sqlserver/server.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index b90f31a1b1..bbdb151efb 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -575,6 +575,12 @@ type heartbeatService struct { } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { + metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + disabled, err := strconv.ParseBool(metricsDisabled) + if err != nil || disabled { + return &heartbeatService{} // will be defunct on Run() + } + cfg, _ := commands.GRPCEventRemoteConfigForEnv(dEnv) return &heartbeatService{version: version, cfg: cfg} } @@ -583,6 +589,11 @@ func (h *heartbeatService) Init(ctx context.Context) error { return nil } func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { + // Faulty config settings or disabled metrics can cause us to not have a valid endpoint + if h.cfg.Endpoint == "" { + return + } + ticker := time.NewTicker(24 * time.Hour) defer ticker.Stop() @@ -598,7 +609,7 @@ func (h *heartbeatService) Run(ctx context.Context) { eventEmitter := events.NewGrpcEmitter(conn) t := events.NowTimestamp() - _ = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ + err = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ { Id: uuid.New().String(), StartTime: t, @@ -607,6 +618,10 @@ func (h *heartbeatService) Run(ctx context.Context) { }, }) + if err != nil { + logrus.Debugf("failed to send heartbeat event: %v", err) + } + _ = conn.Close() } } From e05f2169cfed62e989439a4b39ec472dbe3c53e5 Mon Sep 17 00:00:00 2001 From: zachmu Date: Sat, 2 Dec 2023 02:12:16 +0000 Subject: [PATCH 15/42] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/cmd/dolt/commands/send_metrics.go | 2 +- go/cmd/dolt/commands/sqlserver/server.go | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 1319f6eb01..233cd5d740 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -163,7 +163,7 @@ func GRPCEventRemoteConfigForEnv(dEnv *env.DoltEnv) (dbfactory.GRPCRemoteConfig, } insecure, _ := strconv.ParseBool(insecureStr) - + hostAndPort := fmt.Sprintf("%s:%d", host, port) cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ Endpoint: hostAndPort, diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index bbdb151efb..5f6457cceb 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,7 +26,6 @@ import ( "strings" "time" - "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -44,6 +43,7 @@ import ( "github.com/dolthub/dolt/go/cmd/dolt/commands" "github.com/dolthub/dolt/go/cmd/dolt/commands/engine" eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" + "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/remotesrv" "github.com/dolthub/dolt/go/libraries/doltcore/sqle" @@ -590,10 +590,10 @@ func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { // Faulty config settings or disabled metrics can cause us to not have a valid endpoint - if h.cfg.Endpoint == "" { + if h.cfg.Endpoint == "" { return } - + ticker := time.NewTicker(24 * time.Hour) defer ticker.Stop() @@ -606,22 +606,22 @@ func (h *heartbeatService) Run(ctx context.Context) { if err != nil { continue } - + eventEmitter := events.NewGrpcEmitter(conn) t := events.NowTimestamp() err = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ { - Id: uuid.New().String(), - StartTime: t, - EndTime: t, - Type: eventsapi.ClientEventType_SQL_SERVER_HEARTBEAT, + Id: uuid.New().String(), + StartTime: t, + EndTime: t, + Type: eventsapi.ClientEventType_SQL_SERVER_HEARTBEAT, }, }) - + if err != nil { logrus.Debugf("failed to send heartbeat event: %v", err) } - + _ = conn.Close() } } From 4ec6d2b9fe8352ecdabdc3697177a04f1fde4df0 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Mon, 4 Dec 2023 10:00:58 -0800 Subject: [PATCH 16/42] PR comments --- go/cmd/dolt/cli/arg_parser_helpers.go | 2 +- go/libraries/doltcore/env/actions/clone.go | 21 +++++++-------- integration-tests/bats/remotes.bats | 30 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/go/cmd/dolt/cli/arg_parser_helpers.go b/go/cmd/dolt/cli/arg_parser_helpers.go index eb8cd1ae06..0a04e0f20b 100644 --- a/go/cmd/dolt/cli/arg_parser_helpers.go +++ b/go/cmd/dolt/cli/arg_parser_helpers.go @@ -125,7 +125,7 @@ func CreateCloneArgParser() *argparser.ArgParser { ap.SupportsString(dbfactory.OSSCredsFileParam, "", "file", "OSS credentials file.") ap.SupportsString(dbfactory.OSSCredsProfile, "", "profile", "OSS profile to use.") ap.SupportsString(UserFlag, "u", "user", "User name to use when authenticating with the remote. Gets password from the environment variable {{.EmphasisLeft}}DOLT_REMOTE_PASSWORD{{.EmphasisRight}}.") - ap.SupportsFlag(SingleBranchFlag, "", "Clone only the history leading to the tip of a single branch, either specified by --branch or the primary branch remote's HEAD points at.") + ap.SupportsFlag(SingleBranchFlag, "", "Clone only the history leading to the tip of a single branch, either specified by --branch or the remote's HEAD (default).") return ap } diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index 82d5de273a..e0cac4b902 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -214,27 +214,28 @@ func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch s // every branch in the remote. We iterate through local branches and // create remote refs corresponding to each of them. We delete all of // the local branches except for the one corresponding to |branch|. - for _, brnch := range branches { - if brnch.GetPath() != branch { - err := dEnv.DoltDB.DeleteBranch(ctx, brnch, nil) - if err != nil { - return fmt.Errorf("%w: %s; %s", ErrFailedToDeleteBranch, brnch.String(), err.Error()) - } - } else if !singleBranch || brnch.GetPath() == branch { - cs, _ := doltdb.NewCommitSpec(brnch.GetPath()) + for _, br := range branches { + if !singleBranch || (singleBranch && br.GetPath() == branch) { + cs, _ := doltdb.NewCommitSpec(br.GetPath()) cm, err := dEnv.DoltDB.Resolve(ctx, cs, nil) if err != nil { - return fmt.Errorf("%w: %s; %s", ErrFailedToResolveBranchRef, brnch.String(), err.Error()) + return fmt.Errorf("%w: %s; %s", ErrFailedToResolveBranchRef, br.String(), err.Error()) } - remoteRef := ref.NewRemoteRef(remoteName, brnch.GetPath()) + remoteRef := ref.NewRemoteRef(remoteName, br.GetPath()) err = dEnv.DoltDB.SetHeadToCommit(ctx, remoteRef, cm) if err != nil { return fmt.Errorf("%w: %s; %s", ErrFailedToCreateRemoteRef, remoteRef.String(), err.Error()) } } + if br.GetPath() != branch { + err := dEnv.DoltDB.DeleteBranch(ctx, br, nil) + if err != nil { + return fmt.Errorf("%w: %s; %s", ErrFailedToDeleteBranch, br.String(), err.Error()) + } + } } // TODO: make this interface take a DoltRef and marshal it automatically diff --git a/integration-tests/bats/remotes.bats b/integration-tests/bats/remotes.bats index 0dd65d7d5e..26dbfffb9b 100644 --- a/integration-tests/bats/remotes.bats +++ b/integration-tests/bats/remotes.bats @@ -1023,6 +1023,36 @@ create_five_remote_branches_main_and_master() { [[ ! "$output" =~ "remotes/origin/branch-two" ]] || false } +@test "remotes: clone --branch specifies which branch to clone" { + create_three_remote_branches + cd dolt-repo-clones + dolt clone --branch branch-one http://localhost:50051/test-org/test-repo + cd test-repo + run dolt branch -a + [ "$status" -eq 0 ] + [[ "$output" =~ "* branch-one" ]] || false + [[ ! "$output" =~ " main" ]] || false + [[ ! "$output" =~ " branch-two" ]] || false + [[ "$output" =~ "remotes/origin/main" ]] || false + [[ "$output" =~ "remotes/origin/branch-one" ]] || false + [[ "$output" =~ "remotes/origin/branch-two" ]] || false +} + +@test "remotes: clone --single-branch --branch does not create all remote refs" { + create_three_remote_branches + cd dolt-repo-clones + dolt clone --branch branch-one --single-branch http://localhost:50051/test-org/test-repo + cd test-repo + run dolt branch -a + [ "$status" -eq 0 ] + [[ "$output" =~ "* branch-one" ]] || false + [[ ! "$output" =~ " main" ]] || false + [[ ! "$output" =~ " branch-two" ]] || false + [[ ! "$output" =~ "remotes/origin/main" ]] || false + [[ "$output" =~ "remotes/origin/branch-one" ]] || false + [[ ! "$output" =~ "remotes/origin/branch-two" ]] || false +} + @test "remotes: fetch creates new remote refs for new remote branches" { create_main_remote_branch From 1cd686427e65d634379462aadab6989f3bb7edba Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 11:42:19 -0800 Subject: [PATCH 17/42] Pull out emit func --- go/cmd/dolt/dolt.go | 51 ++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 4015a1800b..d3b5251589 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -209,12 +209,18 @@ Dolt subcommands are in transition to using the flags listed below as global fla Not all subcommands use these flags. If your command accepts these flags without error, then they are supported. ` +const disableEventFlushEnvVar = "DOLT_DISABLE_EVENT_FLUSH" +var eventFlushDisabled = false + func init() { dumpDocsCommand.DoltCommand = doltCommand dumpDocsCommand.GlobalDocs = globalDocs dumpDocsCommand.GlobalSpecialMsg = globalSpecialMsg dumpZshCommand.DoltCommand = doltCommand dfunctions.VersionString = Version + if _, ok := os.LookupEnv(disableEventFlushEnvVar); ok { + eventFlushDisabled = true + } } const pprofServerFlag = "--pprof-server" @@ -466,23 +472,8 @@ func runMain() int { cli.PrintErrln(color.RedString("Failure to parse arguments: %v", err)) return 1 } - - defer func() { - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") - disabled, err := strconv.ParseBool(metricsDisabled) - if err != nil || disabled { - return - } - - // write events - emitter := events.NewFileEmitter(homeDir, dbfactory.DoltDir) - _ = emitter.LogEvents(Version, events.GlobalCollector.Close()) - - // flush events - if len(args) > 0 && shouldFlushEvents(args[0]) { - _ = processEventsDir() - } - }() + + defer emitUsageEvents(dEnv, homeDir, args) if needsWriteAccess(subcommandName) { err = reconfigIfTempFileMoveFails(dEnv) @@ -752,9 +743,31 @@ func seedGlobalRand() { rand.Seed(int64(binary.LittleEndian.Uint64(bs))) } -// processEventsDir flushes all logged events in a separate process. +// emitUsageEvents is called after a command is run to emit usage events and send them to metrics servers. +// Two controls of this behavior are possible: +// 1. The config key |metrics.disabled|, when set to |true|, disables all metrics emission +// 2. The environment key |DOLT_DISABLE_EVENT_FLUSH| allows writing events to disk but not sending them to the server. +// This is mostly used for testing. +func emitUsageEvents(dEnv *env.DoltEnv, homeDir string, args []string) { + metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + disabled, err := strconv.ParseBool(metricsDisabled) + if err != nil || disabled { + return + } + + // write events + emitter := events.NewFileEmitter(homeDir, dbfactory.DoltDir) + _ = emitter.LogEvents(Version, events.GlobalCollector.Close()) + + // flush events + if !eventFlushDisabled && len(args) > 0 && shouldFlushEvents(args[0]) { + _ = flushEventsDir() + } +} + +// flushEventsDir flushes all logged events in a separate process. // This is done without blocking so that the main process can exit immediately in the case of a slow network. -func processEventsDir() error { +func flushEventsDir() error { path, err := os.Executable() if err != nil { return err From 2b33f9c6d1f81798abfa3a328ff40b971c90b52c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 13:33:29 -0800 Subject: [PATCH 18/42] Moved some things around, wrote a factory method --- go/cmd/dolt/commands/send_metrics.go | 45 +----------- go/cmd/dolt/commands/sqlserver/server.go | 2 +- go/libraries/doltcore/env/environment.go | 4 ++ go/libraries/events/emitter.go | 87 ++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 44 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 233cd5d740..f269a87d59 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -16,20 +16,16 @@ package commands import ( "context" - "fmt" "strconv" "time" - "github.com/fatih/color" - "google.golang.org/grpc" - "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" - "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/fatih/color" ) // SendMetricsCommand is the command used for sending metrics @@ -130,47 +126,10 @@ func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir strin if outputToStdio { flusher = events.NewIOFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir) } else { - grpcEmitter := GRPCEventEmitterForEnv(dEnv) + grpcEmitter := events.GRPCEmitterForConfig(dEnv) flusher = events.NewGrpcEventFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, grpcEmitter) } return flusher.Flush(ctx) } -// GRPCEventEmitterForEnv returns an event emitter for the given environment, or nil if the environment cannot -// provide one -func GRPCEventEmitterForEnv(dEnv *env.DoltEnv) *events.GrpcEmitter { - cfg, err := GRPCEventRemoteConfigForEnv(dEnv) - if err != nil { - return nil - } - - conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) - if err != nil { - return nil - } - return events.NewGrpcEmitter(conn) -} - -func GRPCEventRemoteConfigForEnv(dEnv *env.DoltEnv) (dbfactory.GRPCRemoteConfig, error) { - host := dEnv.Config.GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) - portStr := dEnv.Config.GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) - insecureStr := dEnv.Config.GetStringOrDefault(env.MetricsInsecure, "false") - - port, err := strconv.ParseUint(portStr, 10, 16) - if err != nil { - return dbfactory.GRPCRemoteConfig{}, nil - } - - insecure, _ := strconv.ParseBool(insecureStr) - - hostAndPort := fmt.Sprintf("%s:%d", host, port) - cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ - Endpoint: hostAndPort, - Insecure: insecure, - }) - if err != nil { - return dbfactory.GRPCRemoteConfig{}, nil - } - return cfg, err -} diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 5f6457cceb..de1de6785e 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -581,7 +581,7 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { return &heartbeatService{} // will be defunct on Run() } - cfg, _ := commands.GRPCEventRemoteConfigForEnv(dEnv) + cfg, _ := events.GRPCEventRemoteConfig(dEnv) return &heartbeatService{version: version, cfg: cfg} } diff --git a/go/libraries/doltcore/env/environment.go b/go/libraries/doltcore/env/environment.go index 77537b2b87..209d95d6f6 100644 --- a/go/libraries/doltcore/env/environment.go +++ b/go/libraries/doltcore/env/environment.go @@ -105,6 +105,10 @@ func (dEnv *DoltEnv) GetRemoteDB(ctx context.Context, format *types.NomsBinForma } } +func (dEnv *DoltEnv) GetConfig() config.ReadableConfig { + return dEnv.Config +} + func createRepoState(fs filesys.Filesys) (*RepoState, error) { repoState, rsErr := LoadRepoState(fs) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index cce62c2526..4352294d8e 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -18,10 +18,16 @@ import ( "context" "fmt" "io" + "os" "runtime" + "strconv" "strings" "time" + "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" + "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" + "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/prototext" @@ -32,12 +38,27 @@ import ( var Application = eventsapi.AppID_APP_DOLT +const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" +const ( + EmitterTypeNull = "null" + EmitterTypeWriter = "writer" + EmitterTypeGrpc = "grpc" + EmitterTypeFile = "file" +) + // Emitter is an interface used for processing a batch of events type Emitter interface { // LogEvents takes a batch of events and processes them LogEvents(version string, evts []*eventsapi.ClientEvent) error } +// EmitterConfigProvider is an interface used to get the configuration to create an emitter +type EmitterConfigProvider interface { + GetGRPCDialParams(config grpcendpoint.Config) (dbfactory.GRPCRemoteConfig, error) + GetConfig() config.ReadableConfig + GetUserHomeDir() (string, error) +} + // NullEmitter is an emitter that drops events type NullEmitter struct{} @@ -149,3 +170,69 @@ func (fe *FileEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) return nil } + +// NewEmitter returns an emitter for the given configuration provider, keyed off the DOLT_EVENTS_EMITTER environment +// variable. If it's not set, defaults to a file-based emitter. +func NewEmitter(pro EmitterConfigProvider) (Emitter, error) { + envVarType, ok := os.LookupEnv(EmitterTypeEnvVar) + if !ok { + envVarType = EmitterTypeFile + } + + switch envVarType { + case EmitterTypeNull: + return NullEmitter{}, nil + case EmitterTypeWriter: + return WriterEmitter{Wr: os.Stdout}, nil + case EmitterTypeGrpc: + return GRPCEmitterForConfig(pro), nil + case EmitterTypeFile: + homeDir, err := pro.GetUserHomeDir() + if err != nil { + return nil, err + } + return NewFileEmitter(homeDir, dbfactory.DoltDir), nil + default: + return nil, fmt.Errorf("unknown emitter type: %s", envVarType) + } +} + +// GRPCEmitterForConfig returns an event emitter for the given environment, or nil if the environment cannot +// provide one +func GRPCEmitterForConfig(pro EmitterConfigProvider) *GrpcEmitter { + cfg, err := GRPCEventRemoteConfig(pro) + if err != nil { + return nil + } + + conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) + if err != nil { + return nil + } + return NewGrpcEmitter(conn) +} + +// GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider +func GRPCEventRemoteConfig(pro EmitterConfigProvider) (dbfactory.GRPCRemoteConfig, error) { + host := pro.GetConfig().GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) + portStr := pro.GetConfig().GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) + insecureStr := pro.GetConfig().GetStringOrDefault(env.MetricsInsecure, "false") + + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + insecure, _ := strconv.ParseBool(insecureStr) + + hostAndPort := fmt.Sprintf("%s:%d", host, port) + cfg, err := pro.GetGRPCDialParams(grpcendpoint.Config{ + Endpoint: hostAndPort, + Insecure: insecure, + }) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + return cfg, nil +} From 58bb930c95a50c6b8969c578d8383997cdf26aeb Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 13:55:52 -0800 Subject: [PATCH 19/42] Moved config keys out of env package --- go/cmd/dolt/cli/command.go | 7 +-- go/cmd/dolt/commands/commit.go | 11 ++-- go/cmd/dolt/commands/credcmds/check.go | 5 +- go/cmd/dolt/commands/credcmds/import.go | 13 ++--- go/cmd/dolt/commands/credcmds/new.go | 4 +- go/cmd/dolt/commands/credcmds/use.go | 3 +- go/cmd/dolt/commands/init.go | 19 +++---- go/cmd/dolt/commands/init_test.go | 9 ++-- go/cmd/dolt/commands/login.go | 17 ++++--- go/cmd/dolt/commands/merge.go | 5 +- go/cmd/dolt/commands/pull.go | 5 +- go/cmd/dolt/commands/remote_test.go | 6 +-- go/cmd/dolt/commands/send_metrics.go | 3 +- go/cmd/dolt/commands/sqlserver/server.go | 3 +- go/cmd/dolt/dolt.go | 2 +- .../doltcore/dtestutils/environment.go | 5 +- .../dtestutils/testcommands/multienv.go | 5 +- go/libraries/doltcore/env/actions/clone.go | 5 +- go/libraries/doltcore/env/config.go | 32 ++---------- go/libraries/doltcore/env/config_test.go | 48 ++++++++--------- go/libraries/doltcore/env/environment.go | 11 ++-- .../doltcore/env/multi_repo_env_test.go | 5 +- go/libraries/doltcore/env/remotes.go | 2 +- .../doltcore/sqle/dprocedures/dolt_push.go | 3 +- go/libraries/doltcore/sqle/dsess/session.go | 4 +- go/libraries/doltcore/sqle/testutil.go | 4 +- go/libraries/events/emitter.go | 10 ++-- go/libraries/utils/config/keys.go | 51 +++++++++++++++++++ 28 files changed, 170 insertions(+), 127 deletions(-) create mode 100755 go/libraries/utils/config/keys.go diff --git a/go/cmd/dolt/cli/command.go b/go/cmd/dolt/cli/command.go index 51f0bc48d0..60bbab53fb 100644 --- a/go/cmd/dolt/cli/command.go +++ b/go/cmd/dolt/cli/command.go @@ -22,6 +22,7 @@ import ( "strings" "syscall" + config "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" @@ -293,14 +294,14 @@ fatal: empty ident name not allowed // CheckUserNameAndEmail returns true if the user name and email are set for this environment, or prints an error and // returns false if not. -func CheckUserNameAndEmail(config *env.DoltCliConfig) bool { - _, err := config.GetString(env.UserEmailKey) +func CheckUserNameAndEmail(cfg *env.DoltCliConfig) bool { + _, err := cfg.GetString(config.UserEmailKey) if err != nil { PrintErr(userNameRequiredError) return false } - _, err = config.GetString(env.UserNameKey) + _, err = cfg.GetString(config.UserNameKey) if err != nil { PrintErr(userNameRequiredError) return false diff --git a/go/cmd/dolt/commands/commit.go b/go/cmd/dolt/commands/commit.go index bddeb6f672..372d6a8396 100644 --- a/go/cmd/dolt/commands/commit.go +++ b/go/cmd/dolt/commands/commit.go @@ -22,6 +22,7 @@ import ( "os" "strings" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" "github.com/gocraft/dbr/v2" @@ -275,17 +276,17 @@ func handleCommitErr(sqlCtx *sql.Context, queryist cli.Queryist, err error, usag } if err == datas.ErrNameNotConfigured { - bdr := errhand.BuildDError("Could not determine %s.", env.UserNameKey) + bdr := errhand.BuildDError("Could not determine %s.", config.UserNameKey) bdr.AddDetails("Log into DoltHub: dolt login") - bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", env.UserNameKey) + bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", config.UserNameKey) return HandleVErrAndExitCode(bdr.Build(), usage) } if err == datas.ErrEmailNotConfigured { - bdr := errhand.BuildDError("Could not determine %s.", env.UserEmailKey) + bdr := errhand.BuildDError("Could not determine %s.", config.UserEmailKey) bdr.AddDetails("Log into DoltHub: dolt login") - bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", env.UserEmailKey) + bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey) return HandleVErrAndExitCode(bdr.Build(), usage) } @@ -355,7 +356,7 @@ func getCommitMessageFromEditor(sqlCtx *sql.Context, queryist cli.Queryist, sugg backupEd = ed } // try getting Dolt config core.editor - editorStr := cliCtx.Config().GetStringOrDefault(env.DoltEditor, backupEd) + editorStr := cliCtx.Config().GetStringOrDefault(config.DoltEditor, backupEd) cli.ExecuteWithStdioRestored(func() { commitMsg, cErr := editor.OpenCommitEditor(editorStr, initialMsg) diff --git a/go/cmd/dolt/commands/credcmds/check.go b/go/cmd/dolt/commands/credcmds/check.go index 4155596bf6..edb29fe30e 100644 --- a/go/cmd/dolt/commands/credcmds/check.go +++ b/go/cmd/dolt/commands/credcmds/check.go @@ -19,6 +19,7 @@ import ( "fmt" "net" + "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -101,8 +102,8 @@ func loadEndpoint(dEnv *env.DoltEnv, apr *argparser.ArgParseResults) (string, st return getHostFromEndpoint(earg), earg } - host := dEnv.Config.GetStringOrDefault(env.RemotesApiHostKey, env.DefaultRemotesApiHost) - port := dEnv.Config.GetStringOrDefault(env.RemotesApiHostPortKey, env.DefaultRemotesApiPort) + host := dEnv.Config.GetStringOrDefault(config.RemotesApiHostKey, env.DefaultRemotesApiHost) + port := dEnv.Config.GetStringOrDefault(config.RemotesApiHostPortKey, env.DefaultRemotesApiPort) return host, fmt.Sprintf("%s:%s", host, port) } diff --git a/go/cmd/dolt/commands/credcmds/import.go b/go/cmd/dolt/commands/credcmds/import.go index 9323a7a655..5c3251e651 100644 --- a/go/cmd/dolt/commands/credcmds/import.go +++ b/go/cmd/dolt/commands/credcmds/import.go @@ -20,6 +20,7 @@ import ( "io" "os" + "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -149,17 +150,17 @@ func updateProfileWithCredentials(ctx context.Context, dEnv *env.DoltEnv, c cred panic("Should have global config here...") } - if _, err := gcfg.GetString(env.UserNameKey); err == nil { + if _, err := gcfg.GetString(config.UserNameKey); err == nil { // Already has a name... return nil } - if _, err := gcfg.GetString(env.UserEmailKey); err == nil { + if _, err := gcfg.GetString(config.UserEmailKey); err == nil { // Already has an email... return nil } - host := dEnv.Config.GetStringOrDefault(env.RemotesApiHostKey, env.DefaultRemotesApiHost) - port := dEnv.Config.GetStringOrDefault(env.RemotesApiHostPortKey, env.DefaultRemotesApiPort) + host := dEnv.Config.GetStringOrDefault(config.RemotesApiHostKey, env.DefaultRemotesApiHost) + port := dEnv.Config.GetStringOrDefault(config.RemotesApiHostPortKey, env.DefaultRemotesApiPort) hostAndPort := fmt.Sprintf("%s:%s", host, port) cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ Endpoint: hostAndPort, @@ -178,8 +179,8 @@ func updateProfileWithCredentials(ctx context.Context, dEnv *env.DoltEnv, c cred return fmt.Errorf("error: unable to call WhoAmI endpoint: %w", err) } userUpdates := map[string]string{ - env.UserNameKey: resp.DisplayName, - env.UserEmailKey: resp.EmailAddress, + config.UserNameKey: resp.DisplayName, + config.UserEmailKey: resp.EmailAddress, } return gcfg.SetStrings(userUpdates) } diff --git a/go/cmd/dolt/commands/credcmds/new.go b/go/cmd/dolt/commands/credcmds/new.go index 71ee06e538..0979b994c0 100644 --- a/go/cmd/dolt/commands/credcmds/new.go +++ b/go/cmd/dolt/commands/credcmds/new.go @@ -100,9 +100,9 @@ func updateConfigToUseNewCredIfNoExistingCred(dEnv *env.DoltEnv, dCreds creds.Do panic("global config not found. Should create it here if this is a thing.") } - _, err := gcfg.GetString(env.UserCreds) + _, err := gcfg.GetString(config.UserCreds) if err == config.ErrConfigParamNotFound { - return gcfg.SetStrings(map[string]string{env.UserCreds: dCreds.KeyIDBase32Str()}) + return gcfg.SetStrings(map[string]string{config.UserCreds: dCreds.KeyIDBase32Str()}) } else { return err } diff --git a/go/cmd/dolt/commands/credcmds/use.go b/go/cmd/dolt/commands/credcmds/use.go index fd16eedd9d..8189677883 100644 --- a/go/cmd/dolt/commands/credcmds/use.go +++ b/go/cmd/dolt/commands/credcmds/use.go @@ -25,6 +25,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) var useDocs = cli.CommandDocumentationContent{ @@ -95,7 +96,7 @@ func (cmd UseCmd) Exec(ctx context.Context, commandStr string, args []string, dE if !hasGCfg { panic("global config not found. Should create it here if this is a thing.") } - err := gcfg.SetStrings(map[string]string{env.UserCreds: cred.KeyIDBase32Str()}) + err := gcfg.SetStrings(map[string]string{config.UserCreds: cred.KeyIDBase32Str()}) if err != nil { verr = errhand.BuildDError("error: updating user credentials in config").AddCause(err).Build() } diff --git a/go/cmd/dolt/commands/init.go b/go/cmd/dolt/commands/init.go index 761557d424..ea4c451c27 100644 --- a/go/cmd/dolt/commands/init.go +++ b/go/cmd/dolt/commands/init.go @@ -19,6 +19,7 @@ import ( "fmt" "time" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -76,10 +77,10 @@ func (cmd InitCmd) Docs() *cli.CommandDocumentation { func (cmd InitCmd) ArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithMaxArgs(cmd.Name(), 0) - ap.SupportsString(usernameParamName, "", "name", fmt.Sprintf("The name used in commits to this repo. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config.", env.UserNameKey)) - ap.SupportsString(emailParamName, "", "email", fmt.Sprintf("The email address used. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config.", env.UserEmailKey)) + ap.SupportsString(usernameParamName, "", "name", fmt.Sprintf("The name used in commits to this repo. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config.", config.UserNameKey)) + ap.SupportsString(emailParamName, "", "email", fmt.Sprintf("The email address used. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config.", config.UserEmailKey)) ap.SupportsString(cli.DateParam, "", "date", "Specify the date used in the initial commit. If not specified the current system time is used.") - ap.SupportsString(initBranchParamName, "b", "branch", fmt.Sprintf("The branch name used to initialize this database. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config. If unset, the default initialized branch will be named '%s'.", env.InitBranchName, env.DefaultInitBranch)) + ap.SupportsString(initBranchParamName, "b", "branch", fmt.Sprintf("The branch name used to initialize this database. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config. If unset, the default initialized branch will be named '%s'.", config.InitBranchName, env.DefaultInitBranch)) ap.SupportsFlag(newFormatFlag, "", fmt.Sprintf("Specify this flag to use the new storage format (%s).", types.Format_DOLT.VersionString())) ap.SupportsFlag(oldFormatFlag, "", fmt.Sprintf("Specify this flag to use the old storage format (%s).", types.Format_LD_1.VersionString())) ap.SupportsFlag(funHashFlag, "", "") // This flag is an easter egg. We can't currently prevent it from being listed in the help, but the description is deliberately left blank. @@ -123,8 +124,8 @@ func (cmd InitCmd) Exec(ctx context.Context, commandStr string, args []string, d } } - name = dEnv.Config.IfEmptyUseConfig(name, env.UserNameKey) - email = dEnv.Config.IfEmptyUseConfig(email, env.UserEmailKey) + name = dEnv.Config.IfEmptyUseConfig(name, config.UserNameKey) + email = dEnv.Config.IfEmptyUseConfig(email, config.UserEmailKey) if initBranch == "" { initBranch = env.GetDefaultInitBranch(dEnv.Config) } @@ -133,14 +134,14 @@ func (cmd InitCmd) Exec(ctx context.Context, commandStr string, args []string, d cli.PrintErrln( color.RedString("Could not determine %[1]s. "+ "Use the init parameter --name \"FIRST LAST\" to set it for this repo, "+ - "or dolt config --global --add %[1]s \"FIRST LAST\"", env.UserNameKey)) + "or dolt config --global --add %[1]s \"FIRST LAST\"", config.UserNameKey)) usage() return 1 } else if email == "" { cli.PrintErrln( color.RedString("Could not determine %[1]s. "+ "Use the init parameter --email \"EMAIL_ADDRESS\" to set it for this repo, "+ - "or dolt config --global --add %[1]s \"EMAIL_ADDRESS\"", env.UserEmailKey)) + "or dolt config --global --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey)) usage() return 1 } @@ -169,10 +170,10 @@ func (cmd InitCmd) Exec(ctx context.Context, commandStr string, args []string, d configuration := make(map[string]string) if apr.Contains(usernameParamName) { - configuration[env.UserNameKey] = name + configuration[config.UserNameKey] = name } if apr.Contains(emailParamName) { - configuration[env.UserEmailKey] = email + configuration[config.UserEmailKey] = email } if len(configuration) > 0 { err = dEnv.Config.WriteableConfig().SetStrings(configuration) diff --git a/go/cmd/dolt/commands/init_test.go b/go/cmd/dolt/commands/init_test.go index 4973b2e49b..f0fba3f519 100644 --- a/go/cmd/dolt/commands/init_test.go +++ b/go/cmd/dolt/commands/init_test.go @@ -18,6 +18,7 @@ import ( "context" "testing" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/stretchr/testify/require" @@ -45,8 +46,8 @@ func TestInit(t *testing.T) { "Global config name and email", []string{}, map[string]string{ - env.UserNameKey: "Bill Billerson", - env.UserEmailKey: "bigbillieb@fake.horse", + config.UserNameKey: "Bill Billerson", + config.UserEmailKey: "bigbillieb@fake.horse", }, true, }, @@ -80,8 +81,8 @@ func TestInit(t *testing.T) { if test.ExpectSuccess { require.True(t, dEnv.HasDoltDir(), "- .dolt dir should exist after initialization") - testLocalConfigValue(t, dEnv, test, usernameParamName, env.UserNameKey) - testLocalConfigValue(t, dEnv, test, emailParamName, env.UserEmailKey) + testLocalConfigValue(t, dEnv, test, usernameParamName, config.UserNameKey) + testLocalConfigValue(t, dEnv, test, emailParamName, config.UserEmailKey) } else { require.False(t, dEnv.HasDoltDir(), "- dolt directory shouldn't exist after failure to initialize") diff --git a/go/cmd/dolt/commands/login.go b/go/cmd/dolt/commands/login.go index 584d774174..952cd09469 100644 --- a/go/cmd/dolt/commands/login.go +++ b/go/cmd/dolt/commands/login.go @@ -21,6 +21,7 @@ import ( "strconv" "time" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/skratchdot/open-golang/open" "google.golang.org/grpc" @@ -81,7 +82,7 @@ func (cmd LoginCmd) Docs() *cli.CommandDocumentation { func (cmd LoginCmd) ArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithMaxArgs(cmd.Name(), 1) - ap.SupportsString(authEndpointParam, "e", "hostname:port", fmt.Sprintf("Specify the endpoint used to authenticate this client. Must be used with --%s OR set in the configuration file as `%s`", loginURLParam, env.AddCredsUrlKey)) + ap.SupportsString(authEndpointParam, "e", "hostname:port", fmt.Sprintf("Specify the endpoint used to authenticate this client. Must be used with --%s OR set in the configuration file as `%s`", loginURLParam, config.AddCredsUrlKey)) ap.SupportsString(loginURLParam, "url", "url", "Specify the login url where the browser will add credentials.") ap.SupportsFlag(insecureParam, "i", "If set, makes insecure connection to remote authentication server") ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"creds", "A specific credential to use for login. If omitted, new credentials will be generated."}) @@ -100,7 +101,7 @@ func (cmd LoginCmd) Exec(ctx context.Context, commandStr string, args []string, apr := cli.ParseArgsOrDie(ap, args, help) // use config values over defaults, flag values over config values - loginUrl := dEnv.Config.GetStringOrDefault(env.AddCredsUrlKey, env.DefaultLoginUrl) + loginUrl := dEnv.Config.GetStringOrDefault(config.AddCredsUrlKey, env.DefaultLoginUrl) loginUrl = apr.GetValueOrDefault(loginURLParam, loginUrl) var authHost string @@ -114,8 +115,8 @@ func (cmd LoginCmd) Exec(ctx context.Context, commandStr string, args []string, } authEndpoint = fmt.Sprintf("%s:%s", authHost, authPort) } else { - authHost = dEnv.Config.GetStringOrDefault(env.RemotesApiHostKey, env.DefaultRemotesApiHost) - authPort = dEnv.Config.GetStringOrDefault(env.RemotesApiHostPortKey, env.DefaultRemotesApiPort) + authHost = dEnv.Config.GetStringOrDefault(config.RemotesApiHostKey, env.DefaultRemotesApiHost) + authPort = dEnv.Config.GetStringOrDefault(config.RemotesApiHostPortKey, env.DefaultRemotesApiPort) authEndpoint = fmt.Sprintf("%s:%s", authHost, authPort) } @@ -128,10 +129,10 @@ func (cmd LoginCmd) Exec(ctx context.Context, commandStr string, args []string, var err error if !insecure { - insecureStr := dEnv.Config.GetStringOrDefault(env.DoltLabInsecureKey, "false") + insecureStr := dEnv.Config.GetStringOrDefault(config.DoltLabInsecureKey, "false") insecure, err = strconv.ParseBool(insecureStr) if err != nil { - HandleVErrAndExitCode(errhand.BuildDError(fmt.Sprintf("The config value of '%s' is '%s' which is not a valid true/false value", env.DoltLabInsecureKey, insecureStr)).Build(), usage) + HandleVErrAndExitCode(errhand.BuildDError(fmt.Sprintf("The config value of '%s' is '%s' which is not a valid true/false value", config.DoltLabInsecureKey, insecureStr)).Build(), usage) } } @@ -269,9 +270,9 @@ func updateConfig(dEnv *env.DoltEnv, whoAmI *remotesapi.WhoAmIResponse, dCreds c panic("global config not found. Should create it here if this is a thing.") } - gcfg.SetStrings(map[string]string{env.UserCreds: dCreds.KeyIDBase32Str()}) + gcfg.SetStrings(map[string]string{config.UserCreds: dCreds.KeyIDBase32Str()}) - userUpdates := map[string]string{env.UserNameKey: whoAmI.DisplayName, env.UserEmailKey: whoAmI.EmailAddress} + userUpdates := map[string]string{config.UserNameKey: whoAmI.DisplayName, config.UserEmailKey: whoAmI.EmailAddress} lcfg, hasLCfg := dEnv.Config.GetConfig(env.LocalConfig) if hasLCfg { diff --git a/go/cmd/dolt/commands/merge.go b/go/cmd/dolt/commands/merge.go index ac535ffa30..8403acec56 100644 --- a/go/cmd/dolt/commands/merge.go +++ b/go/cmd/dolt/commands/merge.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" "github.com/gocraft/dbr/v2" @@ -174,8 +175,8 @@ func validateDoltMergeArgs(apr *argparser.ArgParseResults, usage cli.UsagePrinte if !cli.CheckUserNameAndEmail(cliCtx.Config()) { bdr := errhand.BuildDError("Could not determine name and/or email.") bdr.AddDetails("Log into DoltHub: dolt login") - bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", env.UserNameKey) - bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", env.UserEmailKey) + bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", config.UserNameKey) + bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey) return HandleVErrAndExitCode(bdr.Build(), usage) } diff --git a/go/cmd/dolt/commands/pull.go b/go/cmd/dolt/commands/pull.go index aa43263b1d..ae51345df2 100644 --- a/go/cmd/dolt/commands/pull.go +++ b/go/cmd/dolt/commands/pull.go @@ -21,6 +21,7 @@ import ( "strings" "time" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/gocraft/dbr/v2" "github.com/gocraft/dbr/v2/dialect" @@ -93,8 +94,8 @@ func (cmd PullCmd) Exec(ctx context.Context, commandStr string, args []string, d if !cli.CheckUserNameAndEmail(cliCtx.Config()) { bdr := errhand.BuildDError("Could not determine name and/or email.") bdr.AddDetails("Log into DoltHub: dolt login") - bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", env.UserNameKey) - bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", env.UserEmailKey) + bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", config.UserNameKey) + bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey) return HandleVErrAndExitCode(bdr.Build(), usage) } diff --git a/go/cmd/dolt/commands/remote_test.go b/go/cmd/dolt/commands/remote_test.go index 638146619d..ef5c6d3ae7 100644 --- a/go/cmd/dolt/commands/remote_test.go +++ b/go/cmd/dolt/commands/remote_test.go @@ -59,7 +59,7 @@ func TestGetAbsRemoteUrl(t *testing.T) { { "ts/emp", config.NewMapConfig(map[string]string{ - env.RemotesApiHostKey: "host.dom", + config.RemotesApiHostKey: "host.dom", }), "https://host.dom/ts/emp", "https", @@ -75,7 +75,7 @@ func TestGetAbsRemoteUrl(t *testing.T) { { "https://test.org:443/ts/emp", config.NewMapConfig(map[string]string{ - env.RemotesApiHostKey: "host.dom", + config.RemotesApiHostKey: "host.dom", }), "https://test.org:443/ts/emp", "https", @@ -84,7 +84,7 @@ func TestGetAbsRemoteUrl(t *testing.T) { { "localhost/ts/emp", config.NewMapConfig(map[string]string{ - env.RemotesApiHostKey: "host.dom", + config.RemotesApiHostKey: "host.dom", }), "https://localhost/ts/emp", "https", diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index f269a87d59..9004c329aa 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -25,6 +25,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" ) @@ -81,7 +82,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{ShortDesc: sendMetricsShortDesc}, ap)) apr := cli.ParseArgsOrDie(ap, args, help) - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + metricsDisabled := dEnv.Config.GetStringOrDefault(config.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) if err != nil { diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index de1de6785e..cb90c49f49 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,6 +26,7 @@ import ( "strings" "time" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -575,7 +576,7 @@ type heartbeatService struct { } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + metricsDisabled := dEnv.Config.GetStringOrDefault(config.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) if err != nil || disabled { return &heartbeatService{} // will be defunct on Run() diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index d3b5251589..27146394ab 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -749,7 +749,7 @@ func seedGlobalRand() { // 2. The environment key |DOLT_DISABLE_EVENT_FLUSH| allows writing events to disk but not sending them to the server. // This is mostly used for testing. func emitUsageEvents(dEnv *env.DoltEnv, homeDir string, args []string) { - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + metricsDisabled := dEnv.Config.GetStringOrDefault(config.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) if err != nil || disabled { return diff --git a/go/libraries/doltcore/dtestutils/environment.go b/go/libraries/doltcore/dtestutils/environment.go index 740ec0e20e..c2d1eddf86 100644 --- a/go/libraries/doltcore/dtestutils/environment.go +++ b/go/libraries/doltcore/dtestutils/environment.go @@ -21,6 +21,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/filesys" "github.com/dolthub/dolt/go/store/types" ) @@ -100,8 +101,8 @@ func createTestEnvWithNameAndFilesystem(envName string, fs filesys.Filesys, home dEnv := env.Load(context.Background(), homeDirFunc, fs, urlStr, "test") cfg, _ := dEnv.Config.GetConfig(env.GlobalConfig) cfg.SetStrings(map[string]string{ - env.UserNameKey: name, - env.UserEmailKey: email, + config.UserNameKey: name, + config.UserEmailKey: email, }) err := dEnv.InitRepo(context.Background(), types.Format_Default, name, email, env.DefaultInitBranch) diff --git a/go/libraries/doltcore/dtestutils/testcommands/multienv.go b/go/libraries/doltcore/dtestutils/testcommands/multienv.go index ecb6ba4db1..3273cc7f20 100644 --- a/go/libraries/doltcore/dtestutils/testcommands/multienv.go +++ b/go/libraries/doltcore/dtestutils/testcommands/multienv.go @@ -22,6 +22,7 @@ import ( cmd "github.com/dolthub/dolt/go/cmd/dolt/commands" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dprocedures" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" @@ -121,8 +122,8 @@ func (mr *MultiRepoTestSetup) NewDB(dbName string) { } cfg, _ := dEnv.Config.GetConfig(env.GlobalConfig) cfg.SetStrings(map[string]string{ - env.UserNameKey: name, - env.UserEmailKey: email, + config.UserNameKey: name, + config.UserEmailKey: email, }) err = dEnv.InitRepo(context.Background(), types.Format_Default, name, email, defaultBranch) if err != nil { diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index f24abd5142..d69b11e3e4 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -22,6 +22,7 @@ import ( "sort" "sync" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dustin/go-humanize" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -267,8 +268,8 @@ func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch s // InitEmptyClonedRepo inits an empty, newly cloned repo. This would be unnecessary if we properly initialized the // storage for a repository when we created it on dolthub. If we do that, this code can be removed. func InitEmptyClonedRepo(ctx context.Context, dEnv *env.DoltEnv) error { - name := dEnv.Config.GetStringOrDefault(env.UserNameKey, "") - email := dEnv.Config.GetStringOrDefault(env.UserEmailKey, "") + name := dEnv.Config.GetStringOrDefault(config.UserNameKey, "") + email := dEnv.Config.GetStringOrDefault(config.UserEmailKey, "") initBranch := env.GetDefaultInitBranch(dEnv.Config) if name == "" { diff --git a/go/libraries/doltcore/env/config.go b/go/libraries/doltcore/env/config.go index cea50a439a..82fa344714 100644 --- a/go/libraries/doltcore/env/config.go +++ b/go/libraries/doltcore/env/config.go @@ -22,7 +22,6 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/filesys" - "github.com/dolthub/dolt/go/libraries/utils/set" "github.com/dolthub/dolt/go/store/datas" ) @@ -30,33 +29,10 @@ const ( localConfigName = "local" globalConfigName = "global" - UserEmailKey = "user.email" - UserNameKey = "user.name" - // should be able to have remote specific creds? - UserCreds = "user.creds" - DoltEditor = "core.editor" - - InitBranchName = "init.defaultbranch" - - RemotesApiHostKey = "remotes.default_host" - RemotesApiHostPortKey = "remotes.default_port" - - AddCredsUrlKey = "creds.add_url" - DoltLabInsecureKey = "doltlab.insecure" - - MetricsDisabled = "metrics.disabled" - MetricsHost = "metrics.host" - MetricsPort = "metrics.port" - MetricsInsecure = "metrics.insecure" - - PushAutoSetupRemote = "push.autosetupremote" ) -var LocalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) -var GlobalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) - // ConfigScope is an enum representing the elements that make up the ConfigHierarchy type ConfigScope int @@ -206,7 +182,7 @@ func GetStringOrDefault(cfg config.ReadableConfig, key, defStr string) string { // GetNameAndEmail returns the name and email from the supplied config func GetNameAndEmail(cfg config.ReadableConfig) (string, string, error) { - name, err := cfg.GetString(UserNameKey) + name, err := cfg.GetString(config.UserNameKey) if err == config.ErrConfigParamNotFound { return "", "", datas.ErrNameNotConfigured @@ -214,7 +190,7 @@ func GetNameAndEmail(cfg config.ReadableConfig) (string, string, error) { return "", "", err } - email, err := cfg.GetString(UserEmailKey) + email, err := cfg.GetString(config.UserEmailKey) if err == config.ErrConfigParamNotFound { return "", "", datas.ErrEmailNotConfigured @@ -258,8 +234,8 @@ const ( ) var DefaultFailsafeConfig = map[string]string{ - UserEmailKey: DefaultEmail, - UserNameKey: DefaultName, + config.UserEmailKey: DefaultEmail, + config.UserNameKey: DefaultName, } func (w writeableLocalDoltCliConfig) SetStrings(updates map[string]string) error { diff --git a/go/libraries/doltcore/env/config_test.go b/go/libraries/doltcore/env/config_test.go index dc363fca1b..0ab85b6042 100644 --- a/go/libraries/doltcore/env/config_test.go +++ b/go/libraries/doltcore/env/config_test.go @@ -34,15 +34,15 @@ func TestConfig(t *testing.T) { lCfg, _ := dEnv.Config.GetConfig(LocalConfig) gCfg, _ := dEnv.Config.GetConfig(GlobalConfig) - lCfg.SetStrings(map[string]string{UserEmailKey: email, UserNameKey: "local_override"}) - gCfg.SetStrings(map[string]string{UserNameKey: name}) + lCfg.SetStrings(map[string]string{config.UserEmailKey: email, config.UserNameKey: "local_override"}) + gCfg.SetStrings(map[string]string{config.UserNameKey: name}) - assert.Equal(t, email, dEnv.Config.GetStringOrDefault(UserEmailKey, "no")) - assert.Equal(t, "local_override", dEnv.Config.GetStringOrDefault(UserNameKey, "no")) + assert.Equal(t, email, dEnv.Config.GetStringOrDefault(config.UserEmailKey, "no")) + assert.Equal(t, "local_override", dEnv.Config.GetStringOrDefault(config.UserNameKey, "no")) assert.Equal(t, "yes", dEnv.Config.GetStringOrDefault("bad_key", "yes")) - assert.Equal(t, email, dEnv.Config.IfEmptyUseConfig("", UserEmailKey)) - assert.Equal(t, "not empty", dEnv.Config.IfEmptyUseConfig("not empty", UserEmailKey)) + assert.Equal(t, email, dEnv.Config.IfEmptyUseConfig("", config.UserEmailKey)) + assert.Equal(t, "not empty", dEnv.Config.IfEmptyUseConfig("not empty", config.UserEmailKey)) assert.Equal(t, "", dEnv.Config.IfEmptyUseConfig("", "missing")) @@ -54,17 +54,17 @@ func TestFailsafes(t *testing.T) { dEnv, _ := createTestEnv(true, true) lCfg, _ := dEnv.Config.GetConfig(LocalConfig) - require.NoError(t, lCfg.Unset([]string{UserNameKey})) + require.NoError(t, lCfg.Unset([]string{config.UserNameKey})) dEnv.Config.SetFailsafes(DefaultFailsafeConfig) - assert.Equal(t, DefaultEmail, dEnv.Config.GetStringOrDefault(UserEmailKey, "none")) - assert.Equal(t, DefaultName, dEnv.Config.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, DefaultEmail, dEnv.Config.GetStringOrDefault(config.UserEmailKey, "none")) + assert.Equal(t, DefaultName, dEnv.Config.GetStringOrDefault(config.UserNameKey, "none")) - dEnv.Config.SetFailsafes(map[string]string{UserEmailKey: "new", "abc": "def"}) + dEnv.Config.SetFailsafes(map[string]string{config.UserEmailKey: "new", "abc": "def"}) - assert.Equal(t, "new", dEnv.Config.GetStringOrDefault(UserEmailKey, "none")) - assert.Equal(t, DefaultName, dEnv.Config.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, "new", dEnv.Config.GetStringOrDefault(config.UserEmailKey, "none")) + assert.Equal(t, DefaultName, dEnv.Config.GetStringOrDefault(config.UserNameKey, "none")) assert.Equal(t, "def", dEnv.Config.GetStringOrDefault("abc", "none")) } @@ -75,23 +75,23 @@ func TestWritableDoltConfig(t *testing.T) { gCfg, _ := dEnv.Config.GetConfig(GlobalConfig) lCfg, _ := dEnv.Config.GetConfig(LocalConfig) - require.NoError(t, gCfg.SetStrings(map[string]string{UserNameKey: name})) - require.NoError(t, lCfg.SetStrings(map[string]string{UserNameKey: localName})) + require.NoError(t, gCfg.SetStrings(map[string]string{config.UserNameKey: name})) + require.NoError(t, lCfg.SetStrings(map[string]string{config.UserNameKey: localName})) cfg := dEnv.Config.WriteableConfig() - assert.Equal(t, localName, cfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, localName, cfg.GetStringOrDefault(config.UserNameKey, "none")) require.NoError(t, cfg.SetStrings(map[string]string{"test": "abc"})) - require.NoError(t, cfg.Unset([]string{UserNameKey})) + require.NoError(t, cfg.Unset([]string{config.UserNameKey})) - assert.Equal(t, name, cfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, name, cfg.GetStringOrDefault(config.UserNameKey, "none")) assert.Equal(t, "abc", cfg.GetStringOrDefault("test", "none")) - _, err := lCfg.GetString(UserNameKey) + _, err := lCfg.GetString(config.UserNameKey) assert.Equal(t, config.ErrConfigParamNotFound, err) - assert.Equal(t, name, gCfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, name, gCfg.GetStringOrDefault(config.UserNameKey, "none")) _, err = gCfg.GetString("test") assert.Equal(t, config.ErrConfigParamNotFound, err) } @@ -102,22 +102,22 @@ func TestWritableDoltConfigNoLocal(t *testing.T) { newName := "Willy" gCfg, _ := dEnv.Config.GetConfig(GlobalConfig) - require.NoError(t, gCfg.SetStrings(map[string]string{UserNameKey: name, "test": "abc"})) + require.NoError(t, gCfg.SetStrings(map[string]string{config.UserNameKey: name, "test": "abc"})) cfg := dEnv.Config.WriteableConfig() - assert.Equal(t, name, cfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, name, cfg.GetStringOrDefault(config.UserNameKey, "none")) assert.Equal(t, "abc", cfg.GetStringOrDefault("test", "none")) - require.NoError(t, cfg.SetStrings(map[string]string{UserNameKey: newName})) + require.NoError(t, cfg.SetStrings(map[string]string{config.UserNameKey: newName})) require.NoError(t, cfg.Unset([]string{"test"})) - assert.Equal(t, newName, cfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, newName, cfg.GetStringOrDefault(config.UserNameKey, "none")) _, err := cfg.GetString("test") assert.Equal(t, config.ErrConfigParamNotFound, err) - assert.Equal(t, newName, gCfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, newName, gCfg.GetStringOrDefault(config.UserNameKey, "none")) _, err = gCfg.GetString("test") assert.Equal(t, config.ErrConfigParamNotFound, err) diff --git a/go/libraries/doltcore/env/environment.go b/go/libraries/doltcore/env/environment.go index 209d95d6f6..9f7b7ba20a 100644 --- a/go/libraries/doltcore/env/environment.go +++ b/go/libraries/doltcore/env/environment.go @@ -46,9 +46,6 @@ const ( DefaultLoginUrl = "https://dolthub.com/settings/credentials" - DefaultMetricsHost = "eventsapi.dolthub.com" - DefaultMetricsPort = "443" - DefaultRemotesApiHost = "doltremoteapi.dolthub.com" DefaultRemotesApiPort = "443" @@ -202,7 +199,7 @@ func Load(ctx context.Context, hdp HomeDirProvider, fs filesys.Filesys, urlStr s } func GetDefaultInitBranch(cfg config.ReadableConfig) string { - return GetStringOrDefault(cfg, InitBranchName, DefaultInitBranch) + return GetStringOrDefault(cfg, config.InitBranchName, DefaultInitBranch) } // Valid returns whether this environment has been properly initialized. This is useful because although every command @@ -814,8 +811,8 @@ func (dEnv *DoltEnv) workingSetMeta() *datas.WorkingSetMeta { func (dEnv *DoltEnv) NewWorkingSetMeta(message string) *datas.WorkingSetMeta { return &datas.WorkingSetMeta{ - Name: dEnv.Config.GetStringOrDefault(UserNameKey, ""), - Email: dEnv.Config.GetStringOrDefault(UserEmailKey, ""), + Name: dEnv.Config.GetStringOrDefault(config.UserNameKey, ""), + Email: dEnv.Config.GetStringOrDefault(config.UserEmailKey, ""), Timestamp: uint64(time.Now().Unix()), Description: message, } @@ -826,7 +823,7 @@ func (dEnv *DoltEnv) CredsDir() (string, error) { } func (dEnv *DoltEnv) UserDoltCreds() (creds.DoltCreds, bool, error) { - kid, err := dEnv.Config.GetString(UserCreds) + kid, err := dEnv.Config.GetString(config.UserCreds) if err == nil && kid != "" { dir, err := dEnv.CredsDir() diff --git a/go/libraries/doltcore/env/multi_repo_env_test.go b/go/libraries/doltcore/env/multi_repo_env_test.go index c5d2674093..b7fbeff7d5 100644 --- a/go/libraries/doltcore/env/multi_repo_env_test.go +++ b/go/libraries/doltcore/env/multi_repo_env_test.go @@ -20,6 +20,7 @@ import ( "path/filepath" "testing" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -103,8 +104,8 @@ func initRepoWithRelativePath(t *testing.T, envPath string, hdp HomeDirProvider) dEnv := Load(context.Background(), hdp, fs, urlStr, "test") cfg, _ := dEnv.Config.GetConfig(GlobalConfig) cfg.SetStrings(map[string]string{ - UserNameKey: name, - UserEmailKey: email, + config.UserNameKey: name, + config.UserEmailKey: email, }) err = dEnv.InitRepo(context.Background(), types.Format_Default, name, email, DefaultInitBranch) diff --git a/go/libraries/doltcore/env/remotes.go b/go/libraries/doltcore/env/remotes.go index 61505b5263..089957041f 100644 --- a/go/libraries/doltcore/env/remotes.go +++ b/go/libraries/doltcore/env/remotes.go @@ -661,7 +661,7 @@ func GetAbsRemoteUrl(fs filesys2.Filesys, cfg config.ReadableConfig, urlArg stri return dbfactory.HTTPSScheme, "https://" + urlArg, nil } - hostName, err := cfg.GetString(RemotesApiHostKey) + hostName, err := cfg.GetString(config.RemotesApiHostKey) if err != nil { if err != config.ErrConfigParamNotFound { diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_push.go b/go/libraries/doltcore/sqle/dprocedures/dolt_push.go index a332771e42..d67626dc1d 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_push.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_push.go @@ -18,6 +18,7 @@ import ( "fmt" "strconv" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" @@ -70,7 +71,7 @@ func doDoltPush(ctx *sql.Context, args []string) (int, string, error) { return cmdFailure, "", err } - autoSetUpRemote := loadConfig(ctx).GetStringOrDefault(env.PushAutoSetupRemote, "false") + autoSetUpRemote := loadConfig(ctx).GetStringOrDefault(config.PushAutoSetupRemote, "false") pushAutoSetUpRemote, err := strconv.ParseBool(autoSetUpRemote) if err != nil { return cmdFailure, "", err diff --git a/go/libraries/doltcore/sqle/dsess/session.go b/go/libraries/doltcore/sqle/dsess/session.go index 1a71596919..442dd7a0bb 100644 --- a/go/libraries/doltcore/sqle/dsess/session.go +++ b/go/libraries/doltcore/sqle/dsess/session.go @@ -95,8 +95,8 @@ func NewDoltSession( conf config.ReadWriteConfig, branchController *branch_control.Controller, ) (*DoltSession, error) { - username := conf.GetStringOrDefault(env.UserNameKey, "") - email := conf.GetStringOrDefault(env.UserEmailKey, "") + username := conf.GetStringOrDefault(config.UserNameKey, "") + email := conf.GetStringOrDefault(config.UserEmailKey, "") globals := config.NewPrefixConfig(conf, env.SqlServerGlobalsPrefix) sess := &DoltSession{ diff --git a/go/libraries/doltcore/sqle/testutil.go b/go/libraries/doltcore/sqle/testutil.go index 99ec7ca619..42823f6a39 100644 --- a/go/libraries/doltcore/sqle/testutil.go +++ b/go/libraries/doltcore/sqle/testutil.go @@ -399,8 +399,8 @@ func CreateTestEnvWithName(envName string) *env.DoltEnv { dEnv := env.Load(context.Background(), homeDirFunc, fs, doltdb.InMemDoltDB+envName, "test") cfg, _ := dEnv.Config.GetConfig(env.GlobalConfig) cfg.SetStrings(map[string]string{ - env.UserNameKey: name, - env.UserEmailKey: email, + config2.UserNameKey: name, + config2.UserEmailKey: email, }) err := dEnv.InitRepo(context.Background(), types.Format_Default, name, email, env.DefaultInitBranch) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 4352294d8e..f2c5576e8c 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -25,7 +25,6 @@ import ( "time" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" - "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" @@ -46,6 +45,9 @@ const ( EmitterTypeFile = "file" ) +const DefaultMetricsHost = "eventsapi.dolthub.com" +const DefaultMetricsPort = "443" + // Emitter is an interface used for processing a batch of events type Emitter interface { // LogEvents takes a batch of events and processes them @@ -214,9 +216,9 @@ func GRPCEmitterForConfig(pro EmitterConfigProvider) *GrpcEmitter { // GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider func GRPCEventRemoteConfig(pro EmitterConfigProvider) (dbfactory.GRPCRemoteConfig, error) { - host := pro.GetConfig().GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) - portStr := pro.GetConfig().GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) - insecureStr := pro.GetConfig().GetStringOrDefault(env.MetricsInsecure, "false") + host := pro.GetConfig().GetStringOrDefault(config.MetricsHost, DefaultMetricsHost) + portStr := pro.GetConfig().GetStringOrDefault(config.MetricsPort, DefaultMetricsPort) + insecureStr := pro.GetConfig().GetStringOrDefault(config.MetricsInsecure, "false") port, err := strconv.ParseUint(portStr, 10, 16) if err != nil { diff --git a/go/libraries/utils/config/keys.go b/go/libraries/utils/config/keys.go new file mode 100755 index 0000000000..a83da32bf8 --- /dev/null +++ b/go/libraries/utils/config/keys.go @@ -0,0 +1,51 @@ +// Copyright 2023 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "github.com/dolthub/dolt/go/libraries/utils/set" +) + +const UserEmailKey = "user.email" + +const UserNameKey = "user.name" + +const UserCreds = "user.creds" + +const DoltEditor = "core.editor" + +const InitBranchName = "init.defaultbranch" + +const RemotesApiHostKey = "remotes.default_host" + +const RemotesApiHostPortKey = "remotes.default_port" + +const AddCredsUrlKey = "creds.add_url" + +const DoltLabInsecureKey = "doltlab.insecure" + +const MetricsDisabled = "metrics.disabled" + +const MetricsHost = "metrics.host" + +const MetricsPort = "metrics.port" + +const MetricsInsecure = "metrics.insecure" + +const PushAutoSetupRemote = "push.autosetupremote" + +var LocalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) +var GlobalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) + From 3a81a6f9a7b3bdfbad2ff4ebd174dc28f104b696 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 15:20:57 -0800 Subject: [PATCH 20/42] Unified flushing --- go/cmd/dolt/commands/send_metrics.go | 31 ++++++------ go/cmd/dolt/commands/sqlserver/server.go | 32 ++++++------ go/libraries/events/emitter.go | 42 ++++++++++++---- go/libraries/events/event_flush.go | 63 ++++++++++++++++++++++++ go/libraries/utils/config/keys.go | 8 --- 5 files changed, 128 insertions(+), 48 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 9004c329aa..b045e46abd 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -32,8 +32,8 @@ import ( // SendMetricsCommand is the command used for sending metrics const ( SendMetricsCommand = "send-metrics" - outputFlag = "output" - sendMetricsShortDesc = "Send metrics to the events server or print them to stdout" + EventsOutputFormat = "output-format" + sendMetricsShortDesc = "Send metrics to the events server (default), or log them in another way" ) type SendMetricsCmd struct{} @@ -65,7 +65,12 @@ func (cmd SendMetricsCmd) Docs() *cli.CommandDocumentation { func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithMaxArgs(cmd.Name(), 0) - ap.SupportsFlag(outputFlag, "o", "Flush events to stdout.") + ap.SupportsString( + EventsOutputFormat, + "r", + "output-format", + "Format of the events output. Valid values are null, writer, grpc, and file.", + ) return ap } @@ -103,9 +108,9 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st if err != nil { return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - - outputToStdio := apr.Contains(outputFlag) - err = FlushLoggedEvents(ctx, dEnv, userHomeDir, outputToStdio) + + output := apr.GetValueOrDefault(EventsOutputFormat, "grpc") + err = FlushLoggedEvents(ctx, dEnv, userHomeDir, output) if err != nil { if err == events.ErrFileLocked { @@ -122,15 +127,13 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st } // FlushLoggedEvents flushes any logged events in the directory given to an appropriate event emitter -func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputToStdio bool) error { - var flusher events.Flusher - if outputToStdio { - flusher = events.NewIOFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir) - } else { - grpcEmitter := events.GRPCEmitterForConfig(dEnv) - flusher = events.NewGrpcEventFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, grpcEmitter) +func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputType string) error { + emitter, err := events.NewEmitter(outputType, dEnv) + if err != nil { + return err } - + + flusher := events.NewFileFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, emitter) return flusher.Flush(ctx) } diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index cb90c49f49..037b3993af 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "net/http" + "os" "runtime" "strconv" "strings" @@ -37,14 +38,12 @@ import ( "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/sirupsen/logrus" - "google.golang.org/grpc" goerrors "gopkg.in/src-d/go-errors.v1" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/commands" "github.com/dolthub/dolt/go/cmd/dolt/commands/engine" eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" - "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/remotesrv" "github.com/dolthub/dolt/go/libraries/doltcore/sqle" @@ -572,7 +571,7 @@ func Serve( // heartbeatService is a service that sends a heartbeat event to the metrics server once a day type heartbeatService struct { version string - cfg dbfactory.GRPCRemoteConfig + eventEmitter events.Emitter } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { @@ -582,16 +581,25 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { return &heartbeatService{} // will be defunct on Run() } - cfg, _ := events.GRPCEventRemoteConfig(dEnv) - return &heartbeatService{version: version, cfg: cfg} + emitterType, ok := os.LookupEnv(events.EmitterTypeEnvVar) + if !ok { + emitterType = events.EmitterTypeGrpc + } + + emitter, err := events.NewEmitter(emitterType, dEnv) + if err != nil { + return &heartbeatService{} // will be defunct on Run() + } + + return &heartbeatService{version: version, eventEmitter: emitter} } func (h *heartbeatService) Init(ctx context.Context) error { return nil } func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { - // Faulty config settings or disabled metrics can cause us to not have a valid endpoint - if h.cfg.Endpoint == "" { + // Faulty config settings or disabled metrics can cause us to not have a valid event emitter + if h.eventEmitter == nil { return } @@ -603,14 +611,8 @@ func (h *heartbeatService) Run(ctx context.Context) { case <-ctx.Done(): return case <-ticker.C: - conn, err := grpc.Dial(h.cfg.Endpoint, h.cfg.DialOptions...) - if err != nil { - continue - } - - eventEmitter := events.NewGrpcEmitter(conn) t := events.NowTimestamp() - err = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ + err := h.eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ { Id: uuid.New().String(), StartTime: t, @@ -622,8 +624,6 @@ func (h *heartbeatService) Run(ctx context.Context) { if err != nil { logrus.Debugf("failed to send heartbeat event: %v", err) } - - _ = conn.Close() } } } diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index f2c5576e8c..886c894188 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -27,6 +27,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/config" + "github.com/fatih/color" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/prototext" @@ -37,6 +38,8 @@ import ( var Application = eventsapi.AppID_APP_DOLT +// EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below +// to change how event emission occurs. This is useful for testing and in some environments. const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" const ( EmitterTypeNull = "null" @@ -50,8 +53,10 @@ const DefaultMetricsPort = "443" // Emitter is an interface used for processing a batch of events type Emitter interface { - // LogEvents takes a batch of events and processes them + // LogEvents emits a batch of events LogEvents(version string, evts []*eventsapi.ClientEvent) error + // LogEventsRequest emits a batch of events wrapped in a request object, with other metadata + LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error } // EmitterConfigProvider is an interface used to get the configuration to create an emitter @@ -69,6 +74,10 @@ func (ne NullEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) e return nil } +func (ne NullEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + return nil +} + // WriterEmitter is an emitter that writes the text encoding of the events to it's writer type WriterEmitter struct { // Wr the writer to log events to @@ -105,7 +114,12 @@ func (we WriterEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) return nil } -// GrpcEmitter sends events to a GRPC service implementing the eventsapi +func (we WriterEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + _, err := fmt.Fprintf(color.Output, "%+v\n", req) + return err +} + + // GrpcEmitter sends events to a GRPC service implementing the eventsapi type GrpcEmitter struct { client eventsapi.ClientEventsServiceClient } @@ -143,6 +157,10 @@ func (em *GrpcEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) return err } +func (em *GrpcEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + return em.SendLogEventsRequest(ctx, req) +} + // SendLogEventsRequest sends a request using the grpc client func (em *GrpcEmitter) SendLogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { _, err := em.client.LogEvents(ctx, req) @@ -173,15 +191,19 @@ func (fe *FileEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) return nil } -// NewEmitter returns an emitter for the given configuration provider, keyed off the DOLT_EVENTS_EMITTER environment -// variable. If it's not set, defaults to a file-based emitter. -func NewEmitter(pro EmitterConfigProvider) (Emitter, error) { - envVarType, ok := os.LookupEnv(EmitterTypeEnvVar) - if !ok { - envVarType = EmitterTypeFile +func (fe *FileEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + // TODO: we are losing some information here, like the machine id + if err := fe.fbp.WriteEvents(req.Version, req.Events); err != nil { + return err } - switch envVarType { + return nil +} + +// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, +// defaults to a file-based emitter. +func NewEmitter(emitterType string, pro EmitterConfigProvider) (Emitter, error) { + switch emitterType { case EmitterTypeNull: return NullEmitter{}, nil case EmitterTypeWriter: @@ -195,7 +217,7 @@ func NewEmitter(pro EmitterConfigProvider) (Emitter, error) { } return NewFileEmitter(homeDir, dbfactory.DoltDir), nil default: - return nil, fmt.Errorf("unknown emitter type: %s", envVarType) + return nil, fmt.Errorf("unknown emitter type: %s", emitterType) } } diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index dace99c86c..c8db25c599 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -47,6 +47,69 @@ type Flusher interface { Flush(ctx context.Context) error } +type FileFlusher struct { + emitter Emitter + fbp *FileBackedProc +} + +func NewFileFlusher(fs filesys.Filesys, userHomeDir string, doltDir string, emitter Emitter) *FileFlusher { + fbp := NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5) + + if exists := fbp.EventsDirExists(); !exists { + panic(ErrEventsDataDir) + } + + return &FileFlusher{emitter: emitter, fbp: fbp} +} + +func (f FileFlusher) Flush(ctx context.Context) error { + fs := f.fbp.GetFileSys() + + evtsDir := f.fbp.GetEventsDirPath() + + err := lockAndFlush(ctx, fs, evtsDir, f.fbp.LockPath, f.flush) + if err != nil { + return err + } + + return nil +} + +// flush has the function signature of the flushCb type +// and sends events data to the events server +func (f FileFlusher) flush(ctx context.Context, path string) error { + fs := f.fbp.GetFileSys() + + data, err := fs.ReadFile(path) + if err != nil { + return err + } + + isFileValid, err := f.fbp.CheckingFunc(data, path) + + if isFileValid && err == nil { + req := &eventsapi.LogEventsRequest{} + + if err := proto.Unmarshal(data, req); err != nil { + return err + } + + if err := f.emitter.LogEventsRequest(ctx, req); err != nil { + return err + } + + if err := fs.DeleteFile(path); err != nil { + return err + } + + return nil + } + + return errInvalidFile +} + +var _ Flusher = &FileFlusher{} + // lockAndFlush locks the given lockPath and passes the flushCB to the filesys' Iter method func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockPath string, fcb flushCB) error { fsLock := filesys.CreateFilesysLock(fs, lockPath) diff --git a/go/libraries/utils/config/keys.go b/go/libraries/utils/config/keys.go index a83da32bf8..57f80654c6 100755 --- a/go/libraries/utils/config/keys.go +++ b/go/libraries/utils/config/keys.go @@ -14,10 +14,6 @@ package config -import ( - "github.com/dolthub/dolt/go/libraries/utils/set" -) - const UserEmailKey = "user.email" const UserNameKey = "user.name" @@ -45,7 +41,3 @@ const MetricsPort = "metrics.port" const MetricsInsecure = "metrics.insecure" const PushAutoSetupRemote = "push.autosetupremote" - -var LocalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) -var GlobalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) - From f1b1521bed9d22fc191dab260d01c87c90933f68 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 15:21:57 -0800 Subject: [PATCH 21/42] Removed unused flusher impls --- go/libraries/events/event_flush.go | 126 +---------------------------- 1 file changed, 2 insertions(+), 124 deletions(-) diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index c8db25c599..82961c5afa 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -17,10 +17,8 @@ package events import ( "context" "errors" - "fmt" "github.com/dolthub/fslock" - "github.com/fatih/color" "google.golang.org/protobuf/proto" eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" @@ -124,7 +122,7 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP }() if err != nil { - if err == fslock.ErrLocked { + if errors.Is(err, fslock.ErrLocked) { return ErrFileLocked } return err @@ -148,124 +146,4 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP } return nil -} - -// GrpcEventFlusher parses dolt event logs sends the events to the events server -type GrpcEventFlusher struct { - em *GrpcEmitter - fbp *FileBackedProc -} - -// NewGrpcEventFlusher creates a new GrpcEventFlusher -func NewGrpcEventFlusher(fs filesys.Filesys, userHomeDir string, doltDir string, grpcEmitter *GrpcEmitter) *GrpcEventFlusher { - fbp := NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5) - - if exists := fbp.EventsDirExists(); !exists { - panic(ErrEventsDataDir) - } - - return &GrpcEventFlusher{em: grpcEmitter, fbp: fbp} -} - -// flush has the function signature of the flushCb type -// and sends events data to the events server -func (egf *GrpcEventFlusher) flush(ctx context.Context, path string) error { - fs := egf.fbp.GetFileSys() - - data, err := fs.ReadFile(path) - if err != nil { - return err - } - - isFileValid, err := egf.fbp.CheckingFunc(data, path) - - if isFileValid && err == nil { - req := &eventsapi.LogEventsRequest{} - - if err := proto.Unmarshal(data, req); err != nil { - return err - } - - if err := egf.em.SendLogEventsRequest(ctx, req); err != nil { - return err - } - - if err := fs.DeleteFile(path); err != nil { - return err - } - - return nil - } - - return errInvalidFile -} - -// Flush satisfies the Flusher interface and calls this Flusher's flush method on each events file -func (egf *GrpcEventFlusher) Flush(ctx context.Context) error { - fs := egf.fbp.GetFileSys() - - evtsDir := egf.fbp.GetEventsDirPath() - - err := lockAndFlush(ctx, fs, evtsDir, egf.fbp.LockPath, egf.flush) - if err != nil { - return err - } - - return nil -} - -// IOFlusher parses event files and writes them to stdout -type IOFlusher struct { - fbp *FileBackedProc -} - -// NewIOFlusher creates a new IOFlusher -func NewIOFlusher(fs filesys.Filesys, userHomeDir string, doltDir string) *IOFlusher { - fbp := NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5) - - if exists := fbp.EventsDirExists(); !exists { - panic(ErrEventsDataDir) - } - - return &IOFlusher{fbp: fbp} -} - -// flush has the function signature of the flushCb type -// and writes data to stdout -func (iof *IOFlusher) flush(ctx context.Context, path string) error { - fs := iof.fbp.GetFileSys() - - data, err := fs.ReadFile(path) - if err != nil { - return err - } - - req := &eventsapi.LogEventsRequest{} - - if err := proto.Unmarshal(data, req); err != nil { - return err - } - - // needed for bats test - fmt.Fprintf(color.Output, "%+v\n", req) - - if err := fs.DeleteFile(path); err != nil { - return err - } - - return nil -} - -// Flush satisfies the Flusher interface and calls this Flusher's flush method on each events file -func (iof *IOFlusher) Flush(ctx context.Context) error { - fs := iof.fbp.GetFileSys() - - evtsDir := iof.fbp.GetEventsDirPath() - - err := lockAndFlush(ctx, fs, evtsDir, iof.fbp.LockPath, iof.flush) - if err != nil { - return err - } - - return nil -} +} \ No newline at end of file From 736941a72c204079e46184db0afc86f98f0f4898 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 15:37:17 -0800 Subject: [PATCH 22/42] Renamed a const --- go/cmd/dolt/commands/send_metrics.go | 4 ++-- go/libraries/events/emitter.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index b045e46abd..a5e7c075fa 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -69,7 +69,7 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { EventsOutputFormat, "r", "output-format", - "Format of the events output. Valid values are null, writer, grpc, and file.", + "Format of the events output. Valid values are null, stdio, grpc, and file.", ) return ap } @@ -109,7 +109,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - output := apr.GetValueOrDefault(EventsOutputFormat, "grpc") + output := apr.GetValueOrDefault(EventsOutputFormat, events.EmitterTypeGrpc) err = FlushLoggedEvents(ctx, dEnv, userHomeDir, output) if err != nil { diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 886c894188..c66ae25021 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -43,7 +43,7 @@ var Application = eventsapi.AppID_APP_DOLT const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" const ( EmitterTypeNull = "null" - EmitterTypeWriter = "writer" + EmitterTypeStdout = "stdout" EmitterTypeGrpc = "grpc" EmitterTypeFile = "file" ) @@ -206,7 +206,7 @@ func NewEmitter(emitterType string, pro EmitterConfigProvider) (Emitter, error) switch emitterType { case EmitterTypeNull: return NullEmitter{}, nil - case EmitterTypeWriter: + case EmitterTypeStdout: return WriterEmitter{Wr: os.Stdout}, nil case EmitterTypeGrpc: return GRPCEmitterForConfig(pro), nil From f9e6922900d21f1ba309e6054293a05c1f16a4b7 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 15:42:02 -0800 Subject: [PATCH 23/42] Configurable heartbeat interval --- go/cmd/dolt/commands/send_metrics.go | 1 - go/cmd/dolt/commands/sqlserver/server.go | 22 ++++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index a5e7c075fa..0432ff37c4 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -75,7 +75,6 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { } // Exec is the implementation of the command that flushes the events to the grpc service -// Exec executes the command func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { if dEnv.DoltDB != nil { // see go/cmd/dolt/dolt.go:interceptSendMetrics() cli.PrintErrln("expected DoltEnv without DoltDB") diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 037b3993af..c6ef70ef03 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -61,6 +61,9 @@ const ( ApiSqleContextKey = "__sqle_context__" ) +// sqlServerHeartbeatIntervalEnvVar is the duration between heartbeats sent to the remote server, used for testing +const sqlServerHeartbeatIntervalEnvVar = "DOLT_SQL_SERVER_HEARTBEAT_INTERVAL" + // ExternalDisableUsers is called by implementing applications to disable users. This is not used by Dolt itself, // but will break compatibility with implementing applications that do not yet support users. var ExternalDisableUsers bool = false @@ -572,6 +575,7 @@ func Serve( type heartbeatService struct { version string eventEmitter events.Emitter + interval time.Duration } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { @@ -591,7 +595,21 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { return &heartbeatService{} // will be defunct on Run() } - return &heartbeatService{version: version, eventEmitter: emitter} + interval, ok := os.LookupEnv(sqlServerHeartbeatIntervalEnvVar) + if !ok { + interval = "24h" + } + + duration, err := time.ParseDuration(interval) + if err != nil { + return nil + } + + return &heartbeatService{ + version: version, + eventEmitter: emitter, + interval: duration, + } } func (h *heartbeatService) Init(ctx context.Context) error { return nil } @@ -603,7 +621,7 @@ func (h *heartbeatService) Run(ctx context.Context) { return } - ticker := time.NewTicker(24 * time.Hour) + ticker := time.NewTicker(h.interval) defer ticker.Stop() for { From a7b31a373637214f8872b7662dd125c493379ca6 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 16:21:59 -0800 Subject: [PATCH 24/42] End to end tests of metrics logging --- integration-tests/bats/send-metrics.bats | 29 ++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/integration-tests/bats/send-metrics.bats b/integration-tests/bats/send-metrics.bats index 312d2f05f4..d561e25ec0 100644 --- a/integration-tests/bats/send-metrics.bats +++ b/integration-tests/bats/send-metrics.bats @@ -17,9 +17,9 @@ teardown() { cp -a $BATS_TEST_DIRNAME/helper/testEvents/* $BATS_TMPDIR/config-$$/.dolt/eventsData/ # kick off two child processes, one should lock the other out of the events dir - dolt send-metrics -output >file1.txt & + dolt send-metrics --output-format stdout >file1.txt & pid1=$! - dolt send-metrics -output >file2.txt & + dolt send-metrics --output-format stdout >file2.txt & pid2=$! # wait for processes to finish @@ -66,3 +66,28 @@ teardown() { echo this block should not fire return 1 } + +@test "send-metrics: test event logging" { + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" + DOLT_DISABLE_EVENT_FLUSH=true dolt ls + DOLT_DISABLE_EVENT_FLUSH=true dolt status + + # output all the metrics data to stdout for examination + run dolt send-metrics --output-format stdout + [ "$status" -eq 0 ] + [ "${#lines[@]}" -eq 4 ] + + # output is random-ordered, so we have to search line in it + sql_count=$(echo "$output" | grep -o "type:SQL" | wc -l) + ls_count=$(echo "$output" | grep -o "type:LS" | wc -l) + status_count=$(echo "$output" | grep -o "type:STATUS" | wc -l) + [ "$sql_count" -eq 2 ] + [ "$ls_count" -eq 1 ] + [ "$status_count" -eq 1 ] + + # send metrics should be empty after this, since it deletes all old metrics + run dolt send-metrics --output-format stdout + [ "$status" -eq 0 ] + [ "$output" == "" ] +} From 41637d5078962baaf29551efed2b30360a1168f7 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 16:22:48 -0800 Subject: [PATCH 25/42] Moved emitter constructor logic out of events packge, where it causes a cycle --- go/cmd/dolt/commands/send_metrics.go | 74 ++++++++++++++++++++++- go/cmd/dolt/commands/sqlserver/server.go | 12 ++-- go/cmd/dolt/commands/status.go | 6 ++ go/libraries/events/emitter.go | 75 +----------------------- 4 files changed, 86 insertions(+), 81 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 0432ff37c4..46fcaae340 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -16,6 +16,8 @@ package commands import ( "context" + "fmt" + "os" "strconv" "time" @@ -23,10 +25,12 @@ import ( "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" + "google.golang.org/grpc" ) // SendMetricsCommand is the command used for sending metrics @@ -127,7 +131,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st // FlushLoggedEvents flushes any logged events in the directory given to an appropriate event emitter func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputType string) error { - emitter, err := events.NewEmitter(outputType, dEnv) + emitter, err := NewEmitter(outputType, dEnv) if err != nil { return err } @@ -136,3 +140,71 @@ func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir strin return flusher.Flush(ctx) } +// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, +// defaults to a file-based emitter. +func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, error) { + switch emitterType { + case events.EmitterTypeNull: + return events.NullEmitter{}, nil + case events.EmitterTypeStdout: + return events.WriterEmitter{Wr: os.Stdout}, nil + case events.EmitterTypeGrpc: + return GRPCEmitterForConfig(pro), nil + case events.EmitterTypeFile: + homeDir, err := pro.GetUserHomeDir() + if err != nil { + return nil, err + } + return events.NewFileEmitter(homeDir, dbfactory.DoltDir), nil + default: + return nil, fmt.Errorf("unknown emitter type: %s", emitterType) + } +} + +// GRPCEmitterForConfig returns an event emitter for the given environment, or nil if the environment cannot +// provide one +func GRPCEmitterForConfig(pro EmitterConfigProvider) *events.GrpcEmitter { + cfg, err := GRPCEventRemoteConfig(pro) + if err != nil { + return nil + } + + conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) + if err != nil { + return nil + } + return events.NewGrpcEmitter(conn) +} + +// GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider +func GRPCEventRemoteConfig(pro EmitterConfigProvider) (dbfactory.GRPCRemoteConfig, error) { + host := pro.GetConfig().GetStringOrDefault(config.MetricsHost, events.DefaultMetricsHost) + portStr := pro.GetConfig().GetStringOrDefault(config.MetricsPort, events.DefaultMetricsPort) + insecureStr := pro.GetConfig().GetStringOrDefault(config.MetricsInsecure, "false") + + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + insecure, _ := strconv.ParseBool(insecureStr) + + hostAndPort := fmt.Sprintf("%s:%d", host, port) + cfg, err := pro.GetGRPCDialParams(grpcendpoint.Config{ + Endpoint: hostAndPort, + Insecure: insecure, + }) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + return cfg, nil +} + +// EmitterConfigProvider is an interface used to get the configuration to create an emitter +type EmitterConfigProvider interface { + GetGRPCDialParams(config grpcendpoint.Config) (dbfactory.GRPCRemoteConfig, error) + GetConfig() config.ReadableConfig + GetUserHomeDir() (string, error) +} + diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index c6ef70ef03..384491065b 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -590,11 +590,6 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { emitterType = events.EmitterTypeGrpc } - emitter, err := events.NewEmitter(emitterType, dEnv) - if err != nil { - return &heartbeatService{} // will be defunct on Run() - } - interval, ok := os.LookupEnv(sqlServerHeartbeatIntervalEnvVar) if !ok { interval = "24h" @@ -602,7 +597,12 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { duration, err := time.ParseDuration(interval) if err != nil { - return nil + return &heartbeatService{} // will be defunct on Run() + } + + emitter, err := commands.NewEmitter(emitterType, dEnv) + if err != nil { + return &heartbeatService{} // will be defunct on Run() } return &heartbeatService{ diff --git a/go/cmd/dolt/commands/status.go b/go/cmd/dolt/commands/status.go index cc87953b29..850cd4fc79 100644 --- a/go/cmd/dolt/commands/status.go +++ b/go/cmd/dolt/commands/status.go @@ -19,6 +19,7 @@ import ( "fmt" "strings" + eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" "github.com/fatih/color" @@ -72,6 +73,7 @@ func (cmd StatusCmd) RequiresRepo() bool { } var _ cli.RepoNotRequiredCommand = StatusCmd{} +var _ cli.EventMonitoredCommand = StatusCmd{} // Name is returns the name of the Dolt cli command. This is what is used on the command line to invoke the command func (cmd StatusCmd) Name() string { @@ -94,6 +96,10 @@ func (cmd StatusCmd) ArgParser() *argparser.ArgParser { return ap } +func (cmd StatusCmd) EventType() eventsapi.ClientEventType { + return eventsapi.ClientEventType_STATUS +} + // Exec executes the command func (cmd StatusCmd) Exec(ctx context.Context, commandStr string, args []string, _ *env.DoltEnv, cliCtx cli.CliContext) int { // parse arguments diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index c66ae25021..7bc56d15a6 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -18,15 +18,10 @@ import ( "context" "fmt" "io" - "os" "runtime" - "strconv" "strings" "time" - "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" - "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/prototext" @@ -59,13 +54,6 @@ type Emitter interface { LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error } -// EmitterConfigProvider is an interface used to get the configuration to create an emitter -type EmitterConfigProvider interface { - GetGRPCDialParams(config grpcendpoint.Config) (dbfactory.GRPCRemoteConfig, error) - GetConfig() config.ReadableConfig - GetUserHomeDir() (string, error) -} - // NullEmitter is an emitter that drops events type NullEmitter struct{} @@ -198,65 +186,4 @@ func (fe *FileEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogE } return nil -} - -// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, -// defaults to a file-based emitter. -func NewEmitter(emitterType string, pro EmitterConfigProvider) (Emitter, error) { - switch emitterType { - case EmitterTypeNull: - return NullEmitter{}, nil - case EmitterTypeStdout: - return WriterEmitter{Wr: os.Stdout}, nil - case EmitterTypeGrpc: - return GRPCEmitterForConfig(pro), nil - case EmitterTypeFile: - homeDir, err := pro.GetUserHomeDir() - if err != nil { - return nil, err - } - return NewFileEmitter(homeDir, dbfactory.DoltDir), nil - default: - return nil, fmt.Errorf("unknown emitter type: %s", emitterType) - } -} - -// GRPCEmitterForConfig returns an event emitter for the given environment, or nil if the environment cannot -// provide one -func GRPCEmitterForConfig(pro EmitterConfigProvider) *GrpcEmitter { - cfg, err := GRPCEventRemoteConfig(pro) - if err != nil { - return nil - } - - conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) - if err != nil { - return nil - } - return NewGrpcEmitter(conn) -} - -// GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider -func GRPCEventRemoteConfig(pro EmitterConfigProvider) (dbfactory.GRPCRemoteConfig, error) { - host := pro.GetConfig().GetStringOrDefault(config.MetricsHost, DefaultMetricsHost) - portStr := pro.GetConfig().GetStringOrDefault(config.MetricsPort, DefaultMetricsPort) - insecureStr := pro.GetConfig().GetStringOrDefault(config.MetricsInsecure, "false") - - port, err := strconv.ParseUint(portStr, 10, 16) - if err != nil { - return dbfactory.GRPCRemoteConfig{}, nil - } - - insecure, _ := strconv.ParseBool(insecureStr) - - hostAndPort := fmt.Sprintf("%s:%d", host, port) - cfg, err := pro.GetGRPCDialParams(grpcendpoint.Config{ - Endpoint: hostAndPort, - Insecure: insecure, - }) - if err != nil { - return dbfactory.GRPCRemoteConfig{}, nil - } - - return cfg, nil -} +} \ No newline at end of file From b207b1bc0394b5424b2b1ee8a61b7bdf8251b672 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 17:03:24 -0800 Subject: [PATCH 26/42] Smoke test for faulty GRPC config, fixed broken error handling in the case of a bad GRPC client --- go/cmd/dolt/commands/send_metrics.go | 52 ++++++++++++------------ go/libraries/events/event_flush.go | 31 +++++++------- integration-tests/bats/send-metrics.bats | 29 +++++++++++++ 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 46fcaae340..e00857c4a6 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -94,7 +94,6 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st disabled, err := strconv.ParseBool(metricsDisabled) if err != nil { - // log.Print(err) return 1 } @@ -103,30 +102,28 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st return 0 } - if !disabled { - ctx, cancel := context.WithTimeout(ctx, time.Minute) - defer cancel() + ctx, cancel := context.WithTimeout(ctx, time.Minute) + defer cancel() - userHomeDir, err := dEnv.GetUserHomeDir() - if err != nil { - return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) - } - - output := apr.GetValueOrDefault(EventsOutputFormat, events.EmitterTypeGrpc) - err = FlushLoggedEvents(ctx, dEnv, userHomeDir, output) - - if err != nil { - if err == events.ErrFileLocked { - return 2 - } - - return 1 - } - - return 0 + userHomeDir, err := dEnv.GetUserHomeDir() + if err != nil { + return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - return 1 + output := apr.GetValueOrDefault(EventsOutputFormat, events.EmitterTypeGrpc) + err = FlushLoggedEvents(ctx, dEnv, userHomeDir, output) + + if err != nil { + cli.PrintErrf("Error flushing events: %s\n", err.Error()) + + if err == events.ErrFileLocked { + return 2 + } + + return 1 + } + + return 0 } // FlushLoggedEvents flushes any logged events in the directory given to an appropriate event emitter @@ -149,7 +146,7 @@ func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, case events.EmitterTypeStdout: return events.WriterEmitter{Wr: os.Stdout}, nil case events.EmitterTypeGrpc: - return GRPCEmitterForConfig(pro), nil + return GRPCEmitterForConfig(pro) case events.EmitterTypeFile: homeDir, err := pro.GetUserHomeDir() if err != nil { @@ -163,17 +160,18 @@ func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, // GRPCEmitterForConfig returns an event emitter for the given environment, or nil if the environment cannot // provide one -func GRPCEmitterForConfig(pro EmitterConfigProvider) *events.GrpcEmitter { +func GRPCEmitterForConfig(pro EmitterConfigProvider) (*events.GrpcEmitter, error) { cfg, err := GRPCEventRemoteConfig(pro) if err != nil { - return nil + return nil, err } conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) if err != nil { - return nil + return nil, err } - return events.NewGrpcEmitter(conn) + + return events.NewGrpcEmitter(conn), nil } // GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index 82961c5afa..e6d0cbcb3a 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -128,22 +128,25 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP return err } - if isUnlocked && err == nil { - err := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { - if err := fcb(ctx, path); err != nil { - // log.Print(err) - return false - } - - return false - }) - - if err != nil { - return err - } - + if !isUnlocked { return nil } + var returnErr error + iterErr := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { + if err := fcb(ctx, path); err != nil { + returnErr = err + return true + } + + return false + }) + + if iterErr != nil { + return iterErr + } else if returnErr != nil { + return returnErr + } + return nil } \ No newline at end of file diff --git a/integration-tests/bats/send-metrics.bats b/integration-tests/bats/send-metrics.bats index d561e25ec0..1c8cdb53c0 100644 --- a/integration-tests/bats/send-metrics.bats +++ b/integration-tests/bats/send-metrics.bats @@ -91,3 +91,32 @@ teardown() { [ "$status" -eq 0 ] [ "$output" == "" ] } + +@test "send-metrics: grpc smoke test" { + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" + DOLT_DISABLE_EVENT_FLUSH=true dolt ls + DOLT_DISABLE_EVENT_FLUSH=true dolt status + + # output all the metrics data to stdout for examination + dolt config --global --add metrics.host "fake.server" + run dolt send-metrics + [ "$status" -eq 1 ] + [[ "$output" =~ "Error flushing events" ]] || false + [[ "$output" =~ "fake.server" ]] || false +} + +# TODO: we need a local metrics server here that we can spin up to verify the send actually works +@test "send-metrics: sql-server heartbeat" { + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" + DOLT_DISABLE_EVENT_FLUSH=true dolt ls + DOLT_DISABLE_EVENT_FLUSH=true dolt status + + # output all the metrics data to stdout for examination + dolt config --global --add metrics.host "fake.server" + dolt send-metrics + [ "$status" -eq 1 ] + [[ "$output" =~ "Error flushing events" ]] || false + [[ "$output" =~ "fake.server" ]] || false +} From 6b54e53586a059d6cea6fca315ae1613d365c61a Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Tue, 5 Dec 2023 09:53:02 -0800 Subject: [PATCH 27/42] simplify single-branch logic --- go/libraries/doltcore/env/actions/clone.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index e0cac4b902..b1c3c6e183 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -215,7 +215,7 @@ func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch s // create remote refs corresponding to each of them. We delete all of // the local branches except for the one corresponding to |branch|. for _, br := range branches { - if !singleBranch || (singleBranch && br.GetPath() == branch) { + if !singleBranch || br.GetPath() == branch { cs, _ := doltdb.NewCommitSpec(br.GetPath()) cm, err := dEnv.DoltDB.Resolve(ctx, cs, nil) if err != nil { From 7271e56ce80dff3205cc380b1de47af26c3c00fa Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 10:03:10 -0800 Subject: [PATCH 28/42] heartbeat tests --- integration-tests/bats/send-metrics.bats | 36 ++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/integration-tests/bats/send-metrics.bats b/integration-tests/bats/send-metrics.bats index 1c8cdb53c0..b10fe2a66e 100644 --- a/integration-tests/bats/send-metrics.bats +++ b/integration-tests/bats/send-metrics.bats @@ -92,6 +92,8 @@ teardown() { [ "$output" == "" ] } +# TODO: we need a local metrics server here that we can spin up to verify the send actually works +# end-to-end @test "send-metrics: grpc smoke test" { DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" @@ -106,17 +108,29 @@ teardown() { [[ "$output" =~ "fake.server" ]] || false } -# TODO: we need a local metrics server here that we can spin up to verify the send actually works @test "send-metrics: sql-server heartbeat" { - DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" - DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" - DOLT_DISABLE_EVENT_FLUSH=true dolt ls - DOLT_DISABLE_EVENT_FLUSH=true dolt status - # output all the metrics data to stdout for examination - dolt config --global --add metrics.host "fake.server" - dolt send-metrics - [ "$status" -eq 1 ] - [[ "$output" =~ "Error flushing events" ]] || false - [[ "$output" =~ "fake.server" ]] || false + DOLT_EVENTS_EMITTER=stdout DOLT_SQL_SERVER_HEARTBEAT_INTERVAL=1s dolt sql-server > heartbeats.out 2>&1 & + server_pid=$! + sleep 5 + kill $server_pid + + wc=`grep SQL_SERVER_HEARTBEAT heartbeats.out | wc -l` + [ $wc -gt 0 ] +} + +# TODO: we need a local metrics server here that we can spin up to verify the send actually works +# end-to-end +@test "send-metrics: sql-server grpc heartbeat smoketest" { + dolt config --global --add metrics.host "fake.server" + DOLT_SQL_SERVER_HEARTBEAT_INTERVAL=1s dolt sql-server -l debug > heartbeats.out 2>&1 & + server_pid=$! + sleep 5 + kill $server_pid + + wc=`grep 'failed to send heartbeat event' heartbeats.out | wc -l` + [ $wc -gt 0 ] + + wc=`grep 'fake.server' heartbeats.out | wc -l` + [ $wc -gt 0 ] } From 8f8c186aaff38b3fe95ff8208ead43c17b28c907 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 10:23:25 -0800 Subject: [PATCH 29/42] bug fix --- go/libraries/events/event_flush.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index e6d0cbcb3a..d8f5daa34d 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -135,6 +135,10 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP var returnErr error iterErr := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { if err := fcb(ctx, path); err != nil { + if errors.Is(err, errInvalidFile) { + // ignore invalid files found in the events directory + return false + } returnErr = err return true } From 13d51ae1aefc00344ffb3c565e4d20627aa3883e Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 11:13:52 -0800 Subject: [PATCH 30/42] fixed test --- integration-tests/bats/send-metrics.bats | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/integration-tests/bats/send-metrics.bats b/integration-tests/bats/send-metrics.bats index b10fe2a66e..90019f2b9d 100644 --- a/integration-tests/bats/send-metrics.bats +++ b/integration-tests/bats/send-metrics.bats @@ -110,11 +110,13 @@ teardown() { @test "send-metrics: sql-server heartbeat" { # output all the metrics data to stdout for examination - DOLT_EVENTS_EMITTER=stdout DOLT_SQL_SERVER_HEARTBEAT_INTERVAL=1s dolt sql-server > heartbeats.out 2>&1 & + DOLT_EVENTS_EMITTER=logger DOLT_SQL_SERVER_HEARTBEAT_INTERVAL=1s dolt sql-server -l debug > heartbeats.out 2>&1 & server_pid=$! sleep 5 kill $server_pid + cat heartbeats.out + wc=`grep SQL_SERVER_HEARTBEAT heartbeats.out | wc -l` [ $wc -gt 0 ] } From 0d78a4ddc21438fd395a7d207c89ef42128680d4 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 11:14:08 -0800 Subject: [PATCH 31/42] Added a logger emitter --- go/cmd/dolt/commands/send_metrics.go | 3 ++ go/libraries/events/emitter.go | 63 +++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index e00857c4a6..666d6a0173 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -30,6 +30,7 @@ import ( "github.com/dolthub/dolt/go/libraries/utils/argparser" "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" + "github.com/sirupsen/logrus" "google.golang.org/grpc" ) @@ -153,6 +154,8 @@ func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, return nil, err } return events.NewFileEmitter(homeDir, dbfactory.DoltDir), nil + case events.EmitterTypeLogger: + return events.NewLoggerEmitter(logrus.DebugLevel), nil default: return nil, fmt.Errorf("unknown emitter type: %s", emitterType) } diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 7bc56d15a6..6d8c1ccad9 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -23,6 +23,7 @@ import ( "time" "github.com/fatih/color" + "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/prototext" @@ -34,13 +35,14 @@ import ( var Application = eventsapi.AppID_APP_DOLT // EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below -// to change how event emission occurs. This is useful for testing and in some environments. +// to change how event emission occurs. This is useful for the send-metrics command, and in some environments. const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" const ( EmitterTypeNull = "null" EmitterTypeStdout = "stdout" EmitterTypeGrpc = "grpc" EmitterTypeFile = "file" + EmitterTypeLogger = "logger" ) const DefaultMetricsHost = "eventsapi.dolthub.com" @@ -186,4 +188,61 @@ func (fe *FileEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogE } return nil -} \ No newline at end of file +} + +type LoggerEmitter struct { + logLevel logrus.Level +} + +func (l LoggerEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) error { + sb := &strings.Builder{} + wr := WriterEmitter{Wr: sb} + err := wr.LogEvents(version, evts) + if err != nil { + return err + } + + eventString := sb.String() + return l.logEventString(eventString) +} + +func (l LoggerEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + sb := &strings.Builder{} + wr := WriterEmitter{Wr: sb} + err := wr.LogEventsRequest(ctx, req) + if err != nil { + return err + } + + eventString := sb.String() + return l.logEventString(eventString) +} + +func (l LoggerEmitter) logEventString(eventString string) error { + switch l.logLevel { + case logrus.DebugLevel: + logrus.Debug(eventString) + case logrus.ErrorLevel: + logrus.Error(eventString) + case logrus.FatalLevel: + logrus.Fatal(eventString) + case logrus.InfoLevel: + logrus.Info(eventString) + case logrus.PanicLevel: + logrus.Panic(eventString) + case logrus.TraceLevel: + logrus.Trace(eventString) + case logrus.WarnLevel: + logrus.Warn(eventString) + default: + return fmt.Errorf("unknown log level %v", l.logLevel) + } + return nil +} + +func NewLoggerEmitter(level logrus.Level) *LoggerEmitter { + return &LoggerEmitter{ + logLevel: level, + } +} + From 07be50d655f8d4cffab0372f4c4225775e4ebd90 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 11:18:01 -0800 Subject: [PATCH 32/42] Fix up docs --- go/cmd/dolt/commands/send_metrics.go | 4 ++-- go/libraries/events/emitter.go | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 666d6a0173..550662cb22 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -38,7 +38,7 @@ import ( const ( SendMetricsCommand = "send-metrics" EventsOutputFormat = "output-format" - sendMetricsShortDesc = "Send metrics to the events server (default), or log them in another way" + sendMetricsShortDesc = "Send usage metrics to the events server (default), or log them in another way" ) type SendMetricsCmd struct{} @@ -74,7 +74,7 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { EventsOutputFormat, "r", "output-format", - "Format of the events output. Valid values are null, stdio, grpc, and file.", + "Format of the events output. Valid values are null, stdout, grpc, file, logger. Defaults to grpc.", ) return ap } diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 6d8c1ccad9..7f2176a6a2 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -35,14 +35,16 @@ import ( var Application = eventsapi.AppID_APP_DOLT // EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below -// to change how event emission occurs. This is useful for the send-metrics command, and in some environments. +// to change how event emission occurs. Currently only used for sql-server heartbeat events. const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" + +// Types of emitters. These strings are accepted by the --output-format flag for the send-metrics command. const ( - EmitterTypeNull = "null" - EmitterTypeStdout = "stdout" - EmitterTypeGrpc = "grpc" - EmitterTypeFile = "file" - EmitterTypeLogger = "logger" + EmitterTypeNull = "null" // no output + EmitterTypeStdout = "stdout" // output to stdout, used in testing + EmitterTypeGrpc = "grpc" // output to a grpc server, the default for send-metrics + EmitterTypeFile = "file" // output to a file, used to log events during normal execution + EmitterTypeLogger = "logger" // output to a logger, used in testing ) const DefaultMetricsHost = "eventsapi.dolthub.com" From 2e963ee8f92fbfcf56d35d9b6e4c888fcd86511c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 11:37:48 -0800 Subject: [PATCH 33/42] Fix test --- go/libraries/events/event_flush_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/libraries/events/event_flush_test.go b/go/libraries/events/event_flush_test.go index d6c75054d2..d56800892d 100644 --- a/go/libraries/events/event_flush_test.go +++ b/go/libraries/events/event_flush_test.go @@ -52,7 +52,7 @@ func NewTestClient() *TestClient { type flushTester struct { Client *TestClient Fbp *FileBackedProc - Flusher *GrpcEventFlusher + Flusher *FileFlusher } func createFlushTester(fs filesys.Filesys, hdir string, ddir string) *flushTester { @@ -62,7 +62,7 @@ func createFlushTester(fs filesys.Filesys, hdir string, ddir string) *flushTeste fbp := NewFileBackedProc(fs, hdir, ddir, sn.Name, sn.Check) - gef := &GrpcEventFlusher{em: &GrpcEmitter{client}, fbp: fbp} + gef := &FileFlusher{emitter: &GrpcEmitter{client}, fbp: fbp} return &flushTester{Client: client, Fbp: fbp, Flusher: gef} } From 59632204cd1f6cb9bb73792d22cc91a998c4a913 Mon Sep 17 00:00:00 2001 From: zachmu Date: Tue, 5 Dec 2023 19:44:51 +0000 Subject: [PATCH 34/42] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/cmd/dolt/cli/command.go | 2 +- go/cmd/dolt/commands/commit.go | 2 +- go/cmd/dolt/commands/credcmds/check.go | 2 +- go/cmd/dolt/commands/credcmds/import.go | 2 +- go/cmd/dolt/commands/init.go | 2 +- go/cmd/dolt/commands/init_test.go | 2 +- go/cmd/dolt/commands/login.go | 2 +- go/cmd/dolt/commands/merge.go | 2 +- go/cmd/dolt/commands/pull.go | 2 +- go/cmd/dolt/commands/send_metrics.go | 20 +++++++++---------- go/cmd/dolt/commands/sqlserver/server.go | 14 ++++++------- go/cmd/dolt/commands/status.go | 2 +- go/cmd/dolt/dolt.go | 11 +++++----- .../eventsapi/v1alpha1/event_constants.pb.go | 5 +++-- go/libraries/doltcore/env/actions/clone.go | 2 +- .../doltcore/env/multi_repo_env_test.go | 2 +- .../doltcore/sqle/dprocedures/dolt_push.go | 2 +- go/libraries/events/emitter.go | 11 +++++----- go/libraries/events/event_flush.go | 10 +++++----- 19 files changed, 49 insertions(+), 48 deletions(-) diff --git a/go/cmd/dolt/cli/command.go b/go/cmd/dolt/cli/command.go index 60bbab53fb..b07a5d8847 100644 --- a/go/cmd/dolt/cli/command.go +++ b/go/cmd/dolt/cli/command.go @@ -22,7 +22,6 @@ import ( "strings" "syscall" - config "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" @@ -30,6 +29,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" + config "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/nbs" "github.com/dolthub/dolt/go/store/types" ) diff --git a/go/cmd/dolt/commands/commit.go b/go/cmd/dolt/commands/commit.go index 372d6a8396..04589bb285 100644 --- a/go/cmd/dolt/commands/commit.go +++ b/go/cmd/dolt/commands/commit.go @@ -22,7 +22,6 @@ import ( "os" "strings" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" "github.com/gocraft/dbr/v2" @@ -38,6 +37,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/editor" "github.com/dolthub/dolt/go/libraries/utils/iohelp" "github.com/dolthub/dolt/go/libraries/utils/set" diff --git a/go/cmd/dolt/commands/credcmds/check.go b/go/cmd/dolt/commands/credcmds/check.go index edb29fe30e..ce11cec726 100644 --- a/go/cmd/dolt/commands/credcmds/check.go +++ b/go/cmd/dolt/commands/credcmds/check.go @@ -19,7 +19,6 @@ import ( "fmt" "net" - "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -31,6 +30,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) var checkShortDesc = "Check authenticating with a credential keypair against a doltremoteapi." diff --git a/go/cmd/dolt/commands/credcmds/import.go b/go/cmd/dolt/commands/credcmds/import.go index 5c3251e651..d39c078b65 100644 --- a/go/cmd/dolt/commands/credcmds/import.go +++ b/go/cmd/dolt/commands/credcmds/import.go @@ -20,7 +20,6 @@ import ( "io" "os" - "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -33,6 +32,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) var importDocs = cli.CommandDocumentationContent{ diff --git a/go/cmd/dolt/commands/init.go b/go/cmd/dolt/commands/init.go index ea4c451c27..a5ef81bcfc 100644 --- a/go/cmd/dolt/commands/init.go +++ b/go/cmd/dolt/commands/init.go @@ -19,7 +19,6 @@ import ( "fmt" "time" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -27,6 +26,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/dconfig" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/datas" "github.com/dolthub/dolt/go/store/types" ) diff --git a/go/cmd/dolt/commands/init_test.go b/go/cmd/dolt/commands/init_test.go index f0fba3f519..ab5a411d1e 100644 --- a/go/cmd/dolt/commands/init_test.go +++ b/go/cmd/dolt/commands/init_test.go @@ -18,13 +18,13 @@ import ( "context" "testing" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/stretchr/testify/require" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) type initTest struct { diff --git a/go/cmd/dolt/commands/login.go b/go/cmd/dolt/commands/login.go index 952cd09469..35ae1ac209 100644 --- a/go/cmd/dolt/commands/login.go +++ b/go/cmd/dolt/commands/login.go @@ -21,7 +21,6 @@ import ( "strconv" "time" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/skratchdot/open-golang/open" "google.golang.org/grpc" @@ -34,6 +33,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) const ( diff --git a/go/cmd/dolt/commands/merge.go b/go/cmd/dolt/commands/merge.go index 8403acec56..ad93fb17c5 100644 --- a/go/cmd/dolt/commands/merge.go +++ b/go/cmd/dolt/commands/merge.go @@ -23,7 +23,6 @@ import ( "strconv" "strings" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" "github.com/gocraft/dbr/v2" @@ -37,6 +36,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/merge" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/util/outputpager" ) diff --git a/go/cmd/dolt/commands/pull.go b/go/cmd/dolt/commands/pull.go index ae51345df2..9362f335e1 100644 --- a/go/cmd/dolt/commands/pull.go +++ b/go/cmd/dolt/commands/pull.go @@ -21,7 +21,6 @@ import ( "strings" "time" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/gocraft/dbr/v2" "github.com/gocraft/dbr/v2/dialect" @@ -32,6 +31,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/util/outputpager" ) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 550662cb22..4cc2a6243d 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -21,6 +21,10 @@ import ( "strconv" "time" + "github.com/fatih/color" + "github.com/sirupsen/logrus" + "google.golang.org/grpc" + "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" @@ -29,15 +33,12 @@ import ( "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" "github.com/dolthub/dolt/go/libraries/utils/config" - "github.com/fatih/color" - "github.com/sirupsen/logrus" - "google.golang.org/grpc" ) // SendMetricsCommand is the command used for sending metrics const ( SendMetricsCommand = "send-metrics" - EventsOutputFormat = "output-format" + EventsOutputFormat = "output-format" sendMetricsShortDesc = "Send usage metrics to the events server (default), or log them in another way" ) @@ -74,7 +75,7 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { EventsOutputFormat, "r", "output-format", - "Format of the events output. Valid values are null, stdout, grpc, file, logger. Defaults to grpc.", + "Format of the events output. Valid values are null, stdout, grpc, file, logger. Defaults to grpc.", ) return ap } @@ -120,7 +121,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st if err == events.ErrFileLocked { return 2 } - + return 1 } @@ -133,12 +134,12 @@ func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir strin if err != nil { return err } - + flusher := events.NewFileFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, emitter) return flusher.Flush(ctx) } -// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, +// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, // defaults to a file-based emitter. func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, error) { switch emitterType { @@ -173,7 +174,7 @@ func GRPCEmitterForConfig(pro EmitterConfigProvider) (*events.GrpcEmitter, error if err != nil { return nil, err } - + return events.NewGrpcEmitter(conn), nil } @@ -208,4 +209,3 @@ type EmitterConfigProvider interface { GetConfig() config.ReadableConfig GetUserHomeDir() (string, error) } - diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 384491065b..c34a6cd9c1 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -27,7 +27,6 @@ import ( "strings" "time" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -53,6 +52,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" "github.com/dolthub/dolt/go/libraries/doltcore/sqlserver" "github.com/dolthub/dolt/go/libraries/events" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/svcs" ) @@ -573,9 +573,9 @@ func Serve( // heartbeatService is a service that sends a heartbeat event to the metrics server once a day type heartbeatService struct { - version string + version string eventEmitter events.Emitter - interval time.Duration + interval time.Duration } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { @@ -599,16 +599,16 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { if err != nil { return &heartbeatService{} // will be defunct on Run() } - + emitter, err := commands.NewEmitter(emitterType, dEnv) if err != nil { return &heartbeatService{} // will be defunct on Run() } - + return &heartbeatService{ - version: version, + version: version, eventEmitter: emitter, - interval: duration, + interval: duration, } } diff --git a/go/cmd/dolt/commands/status.go b/go/cmd/dolt/commands/status.go index 850cd4fc79..1747762c3a 100644 --- a/go/cmd/dolt/commands/status.go +++ b/go/cmd/dolt/commands/status.go @@ -19,13 +19,13 @@ import ( "fmt" "strings" - eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" "github.com/fatih/color" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" + eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/utils/argparser" diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 27146394ab..ddaadcd37f 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -210,6 +210,7 @@ Not all subcommands use these flags. If your command accepts these flags without ` const disableEventFlushEnvVar = "DOLT_DISABLE_EVENT_FLUSH" + var eventFlushDisabled = false func init() { @@ -219,7 +220,7 @@ func init() { dumpZshCommand.DoltCommand = doltCommand dfunctions.VersionString = Version if _, ok := os.LookupEnv(disableEventFlushEnvVar); ok { - eventFlushDisabled = true + eventFlushDisabled = true } } @@ -472,7 +473,7 @@ func runMain() int { cli.PrintErrln(color.RedString("Failure to parse arguments: %v", err)) return 1 } - + defer emitUsageEvents(dEnv, homeDir, args) if needsWriteAccess(subcommandName) { @@ -745,9 +746,9 @@ func seedGlobalRand() { // emitUsageEvents is called after a command is run to emit usage events and send them to metrics servers. // Two controls of this behavior are possible: -// 1. The config key |metrics.disabled|, when set to |true|, disables all metrics emission -// 2. The environment key |DOLT_DISABLE_EVENT_FLUSH| allows writing events to disk but not sending them to the server. -// This is mostly used for testing. +// 1. The config key |metrics.disabled|, when set to |true|, disables all metrics emission +// 2. The environment key |DOLT_DISABLE_EVENT_FLUSH| allows writing events to disk but not sending them to the server. +// This is mostly used for testing. func emitUsageEvents(dEnv *env.DoltEnv, homeDir string, args []string) { metricsDisabled := dEnv.Config.GetStringOrDefault(config.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go index 8d23ad67a9..a180d1b5a3 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go @@ -23,10 +23,11 @@ package eventsapi import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index d69b11e3e4..106aa5be08 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -22,7 +22,6 @@ import ( "sort" "sync" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dustin/go-humanize" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -30,6 +29,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/ref" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/filesys" "github.com/dolthub/dolt/go/libraries/utils/iohelp" "github.com/dolthub/dolt/go/libraries/utils/strhelp" diff --git a/go/libraries/doltcore/env/multi_repo_env_test.go b/go/libraries/doltcore/env/multi_repo_env_test.go index b7fbeff7d5..9a5b6bdb82 100644 --- a/go/libraries/doltcore/env/multi_repo_env_test.go +++ b/go/libraries/doltcore/env/multi_repo_env_test.go @@ -20,12 +20,12 @@ import ( "path/filepath" "testing" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/dconfig" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/earl" "github.com/dolthub/dolt/go/libraries/utils/filesys" "github.com/dolthub/dolt/go/libraries/utils/test" diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_push.go b/go/libraries/doltcore/sqle/dprocedures/dolt_push.go index d67626dc1d..309446de9b 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_push.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_push.go @@ -18,7 +18,6 @@ import ( "fmt" "strconv" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" @@ -28,6 +27,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/datas" ) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 7f2176a6a2..2eacaaca77 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -34,16 +34,16 @@ import ( var Application = eventsapi.AppID_APP_DOLT -// EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below +// EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below // to change how event emission occurs. Currently only used for sql-server heartbeat events. const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" // Types of emitters. These strings are accepted by the --output-format flag for the send-metrics command. const ( - EmitterTypeNull = "null" // no output + EmitterTypeNull = "null" // no output EmitterTypeStdout = "stdout" // output to stdout, used in testing - EmitterTypeGrpc = "grpc" // output to a grpc server, the default for send-metrics - EmitterTypeFile = "file" // output to a file, used to log events during normal execution + EmitterTypeGrpc = "grpc" // output to a grpc server, the default for send-metrics + EmitterTypeFile = "file" // output to a file, used to log events during normal execution EmitterTypeLogger = "logger" // output to a logger, used in testing ) @@ -111,7 +111,7 @@ func (we WriterEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.Log return err } - // GrpcEmitter sends events to a GRPC service implementing the eventsapi +// GrpcEmitter sends events to a GRPC service implementing the eventsapi type GrpcEmitter struct { client eventsapi.ClientEventsServiceClient } @@ -247,4 +247,3 @@ func NewLoggerEmitter(level logrus.Level) *LoggerEmitter { logLevel: level, } } - diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index d8f5daa34d..c427efc62d 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -47,12 +47,12 @@ type Flusher interface { type FileFlusher struct { emitter Emitter - fbp *FileBackedProc + fbp *FileBackedProc } func NewFileFlusher(fs filesys.Filesys, userHomeDir string, doltDir string, emitter Emitter) *FileFlusher { fbp := NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5) - + if exists := fbp.EventsDirExists(); !exists { panic(ErrEventsDataDir) } @@ -145,12 +145,12 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP return false }) - + if iterErr != nil { return iterErr } else if returnErr != nil { return returnErr } - + return nil -} \ No newline at end of file +} From 9d3d1ca3e0bf5406ad3dd230ca57fe0b56fb034a Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 12:25:54 -0800 Subject: [PATCH 35/42] Test fixes --- go/libraries/events/event_flush.go | 6 +- go/libraries/events/event_flush_test.go | 59 ++++++++++---------- go/libraries/events/file_backed_proc_test.go | 6 +- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index d8f5daa34d..f2fa3cd899 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -65,7 +65,7 @@ func (f FileFlusher) Flush(ctx context.Context) error { evtsDir := f.fbp.GetEventsDirPath() - err := lockAndFlush(ctx, fs, evtsDir, f.fbp.LockPath, f.flush) + err := f.lockAndFlush(ctx, fs, evtsDir, f.fbp.LockPath) if err != nil { return err } @@ -109,7 +109,7 @@ func (f FileFlusher) flush(ctx context.Context, path string) error { var _ Flusher = &FileFlusher{} // lockAndFlush locks the given lockPath and passes the flushCB to the filesys' Iter method -func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockPath string, fcb flushCB) error { +func (f FileFlusher) lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockPath string) error { fsLock := filesys.CreateFilesysLock(fs, lockPath) isUnlocked, err := fsLock.TryLock() @@ -134,7 +134,7 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP var returnErr error iterErr := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { - if err := fcb(ctx, path); err != nil { + if err := f.flush(ctx, path); err != nil { if errors.Is(err, errInvalidFile) { // ignore invalid files found in the events directory return false diff --git a/go/libraries/events/event_flush_test.go b/go/libraries/events/event_flush_test.go index d56800892d..bb98c7d455 100644 --- a/go/libraries/events/event_flush_test.go +++ b/go/libraries/events/event_flush_test.go @@ -86,46 +86,49 @@ func TestEventFlushing(t *testing.T) { }, } - filesystems := []string{"inMemFS", "local"} - + // filesystems := []string{"inMemFS", "local"} + filesystems := []string{"local"} + for _, fsName := range filesystems { - for _, test := range tests { + t.Run(fsName, func(t *testing.T) { + for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - ctx := context.Background() + t.Run(test.name, func(t *testing.T) { + ctx := context.Background() - var ft *flushTester + var ft *flushTester - if fsName == "inMemFS" { - fs := filesys.NewInMemFS([]string{tempEvtsDir}, nil, tempEvtsDir) + if fsName == "inMemFS" { + fs := filesys.NewInMemFS([]string{tempEvtsDir}, nil, tempEvtsDir) - ft = createFlushTester(fs, homeDir, doltTestDir) - } else { - fs := filesys.LocalFS + ft = createFlushTester(fs, homeDir, doltTestDir) + } else { + fs := filesys.LocalFS - path := filepath.Join(dPath, evtPath) - dDir := testLib.TestDir(path) + path := filepath.Join(dPath, evtPath) + dDir := testLib.TestDir(path) - ft = createFlushTester(fs, "", dDir) - } + ft = createFlushTester(fs, "", dDir) + } - ces := make([]*eventsapi.ClientEvent, 0) + ces := make([]*eventsapi.ClientEvent, 0) - for i := 0; i < test.numEvents; i++ { - ce := &eventsapi.ClientEvent{} - ces = append(ces, ce) - } + for i := 0; i < test.numEvents; i++ { + ce := &eventsapi.ClientEvent{} + ces = append(ces, ce) + } - assert.Equal(t, len(ces), test.numEvents) + assert.Equal(t, len(ces), test.numEvents) - err := ft.Fbp.WriteEvents(testVersion, ces) - assert.Equal(t, err, nil) + err := ft.Fbp.WriteEvents(testVersion, ces) + assert.Equal(t, err, nil) - err = ft.Flusher.Flush(ctx) + err = ft.Flusher.Flush(ctx) - assert.Equal(t, err, nil) - assert.Equal(t, len(ft.Client.CES), len(ces)) - }) - } + assert.NoError(t, err) + assert.Equal(t, len(ft.Client.CES), len(ces)) + }) + } + }) } } diff --git a/go/libraries/events/file_backed_proc_test.go b/go/libraries/events/file_backed_proc_test.go index fb1f9f5fcd..0deefb64b4 100644 --- a/go/libraries/events/file_backed_proc_test.go +++ b/go/libraries/events/file_backed_proc_test.go @@ -42,8 +42,10 @@ func (namer *SequentialNamer) Name(bytes []byte) string { } func (namer *SequentialNamer) Check(data []byte, path string) (bool, error) { - // todo - return true, nil + filename := filepath.Base(path) + ext := filepath.Ext(filename) + + return ext == evtDataExt, nil } func (namer *SequentialNamer) GetIdx() int { From e4389240b5756972ff2222c951b5986a4632ed12 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 12:41:17 -0800 Subject: [PATCH 36/42] Bug fix for windows lock file --- go/libraries/events/event_flush.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index 8407153509..91cbdf0a4d 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -17,6 +17,7 @@ package events import ( "context" "errors" + "io/fs" "github.com/dolthub/fslock" "google.golang.org/protobuf/proto" @@ -109,8 +110,8 @@ func (f FileFlusher) flush(ctx context.Context, path string) error { var _ Flusher = &FileFlusher{} // lockAndFlush locks the given lockPath and passes the flushCB to the filesys' Iter method -func (f FileFlusher) lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockPath string) error { - fsLock := filesys.CreateFilesysLock(fs, lockPath) +func (f FileFlusher) lockAndFlush(ctx context.Context, fsys filesys.Filesys, dirPath string, lockPath string) error { + fsLock := filesys.CreateFilesysLock(fsys, lockPath) isUnlocked, err := fsLock.TryLock() defer func() error { @@ -133,11 +134,15 @@ func (f FileFlusher) lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPa } var returnErr error - iterErr := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { + iterErr := fsys.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { if err := f.flush(ctx, path); err != nil { if errors.Is(err, errInvalidFile) { // ignore invalid files found in the events directory return false + } else if _, isPathError := err.(*fs.PathError); isPathError { + // The lock file on windows has this issue, skip this file + // We can't use errors.Is because fs.PathError doesn't implement Is + return false } returnErr = err return true From d3cda14fe346e7dfc4b679ce77c1fbe383d97db4 Mon Sep 17 00:00:00 2001 From: zachmu Date: Tue, 5 Dec 2023 20:48:00 +0000 Subject: [PATCH 37/42] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/libraries/events/event_flush_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/events/event_flush_test.go b/go/libraries/events/event_flush_test.go index bb98c7d455..bab36338cd 100644 --- a/go/libraries/events/event_flush_test.go +++ b/go/libraries/events/event_flush_test.go @@ -88,7 +88,7 @@ func TestEventFlushing(t *testing.T) { // filesystems := []string{"inMemFS", "local"} filesystems := []string{"local"} - + for _, fsName := range filesystems { t.Run(fsName, func(t *testing.T) { for _, test := range tests { From 8ae7445ef8e216aef9ee09e1a69c86ea208fc4da Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 12:48:49 -0800 Subject: [PATCH 38/42] Upgrade hadoop (older version now gone) --- .github/workflows/ci-bats-unix-remote.yaml | 6 +++--- .github/workflows/ci-bats-unix.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-bats-unix-remote.yaml b/.github/workflows/ci-bats-unix-remote.yaml index ee8a98dc06..7302c351bd 100644 --- a/.github/workflows/ci-bats-unix-remote.yaml +++ b/.github/workflows/ci-bats-unix-remote.yaml @@ -93,9 +93,9 @@ jobs: - name: Install Hadoop working-directory: ./.ci_bin run: | - curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.4/hadoop-3.3.4.tar.gz - tar xvf hadoop-3.3.4.tar.gz - echo "$(pwd)/hadoop-3.3.4/bin" >> $GITHUB_PATH + curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz + tar xvf hadoop-3.3.6.tar.gz + echo "$(pwd)/hadoop-3.3.6/bin" >> $GITHUB_PATH - name: Install parquet-cli id: parquet_cli working-directory: ./.ci_bin diff --git a/.github/workflows/ci-bats-unix.yaml b/.github/workflows/ci-bats-unix.yaml index 126b40a18d..e6db9efb50 100644 --- a/.github/workflows/ci-bats-unix.yaml +++ b/.github/workflows/ci-bats-unix.yaml @@ -93,9 +93,9 @@ jobs: - name: Install Hadoop working-directory: ./.ci_bin run: | - curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.4/hadoop-3.3.4.tar.gz - tar xvf hadoop-3.3.4.tar.gz - echo "$(pwd)/hadoop-3.3.4/bin" >> $GITHUB_PATH + curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz + tar xvf hadoop-3.3.6.tar.gz + echo "$(pwd)/hadoop-3.3.6/bin" >> $GITHUB_PATH - name: Install parquet-cli id: parquet_cli working-directory: ./.ci_bin From f54aa12850ba2b1cec289c0c28b3f041eb5de710 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 13:56:24 -0800 Subject: [PATCH 39/42] Uncommented debug code --- go/libraries/events/event_flush_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/go/libraries/events/event_flush_test.go b/go/libraries/events/event_flush_test.go index bab36338cd..1798aba4db 100644 --- a/go/libraries/events/event_flush_test.go +++ b/go/libraries/events/event_flush_test.go @@ -86,8 +86,7 @@ func TestEventFlushing(t *testing.T) { }, } - // filesystems := []string{"inMemFS", "local"} - filesystems := []string{"local"} + filesystems := []string{"inMemFS", "local"} for _, fsName := range filesystems { t.Run(fsName, func(t *testing.T) { From 6c5c03dffe773a8428804478b3130d6269c01b30 Mon Sep 17 00:00:00 2001 From: Aaron Son Date: Tue, 5 Dec 2023 11:33:01 -0800 Subject: [PATCH 40/42] integration-tests/bats: Small bats tests improvements for the lambda runner. --- integration-tests/bats/bats.bats | 4 ++-- integration-tests/bats/config.bats | 1 - integration-tests/bats/dump.bats | 10 +++++----- integration-tests/bats/export-tables.bats | 2 ++ integration-tests/bats/log.bats | 3 ++- integration-tests/bats/regression-tests.bats | 1 + integration-tests/bats/sql-diff.bats | 2 +- integration-tests/bats/sql-server.bats | 7 +++++-- integration-tests/bats/sql-shell.bats | 5 +++++ integration-tests/bats/sql.bats | 1 + integration-tests/bats/status.bats | 2 +- integration-tests/bats/validation.bats | 2 +- 12 files changed, 26 insertions(+), 14 deletions(-) diff --git a/integration-tests/bats/bats.bats b/integration-tests/bats/bats.bats index c97f79e32d..9e64a0b200 100644 --- a/integration-tests/bats/bats.bats +++ b/integration-tests/bats/bats.bats @@ -3,9 +3,9 @@ # Assert that all bash test constructs will correctly fail on Mac OS's older bash version # by ending them with '|| false'. # https://github.com/sstephenson/bats/issues/49 -@test "bats: all bash test constructs end with '|| false' { +@test "bats: all bash test constructs end with '|| false'" { run grep -E ' *\]\][[:space:]]*$' -n *.bats # grep returns 0 if matches are found, 1 if matches are NOT found, and 2 if no input files were found echo -e "Incorrect bash test constructs: \n$output" [ $status -eq 1 ] -} \ No newline at end of file +} diff --git a/integration-tests/bats/config.bats b/integration-tests/bats/config.bats index f9e0cf0b32..32a6586626 100644 --- a/integration-tests/bats/config.bats +++ b/integration-tests/bats/config.bats @@ -36,7 +36,6 @@ teardown() { [ "$status" -eq 0 ] # Need to make this a regex because of the coloring [[ "$output" =~ "Config successfully updated" ]] || false - [ -f `nativepath ~/.dolt/config_global.json` ] run dolt config --list [ "$status" -eq 0 ] [ "$output" = "test = test" ] diff --git a/integration-tests/bats/dump.bats b/integration-tests/bats/dump.bats index 622c3b7296..43c3ca4de9 100644 --- a/integration-tests/bats/dump.bats +++ b/integration-tests/bats/dump.bats @@ -151,7 +151,7 @@ teardown() { [[ "$output" =~ "3,Table" ]] || false } -@test "dump: SQL type - compare tables in database with tables imported file " { +@test "dump: SQL type - compare tables in database with tables imported file" { dolt branch new_branch dolt sql -q "CREATE TABLE new_table(pk int primary key);" dolt sql -q "INSERT INTO new_table VALUES (1);" @@ -176,7 +176,7 @@ teardown() { [[ "$output" = "" ]] || false } -@test "dump: SQL type (no-batch) - compare tables in database with tables imported file " { +@test "dump: SQL type (no-batch) - compare tables in database with tables imported file" { dolt branch new_branch dolt sql -q "CREATE TABLE new_table(pk int primary key);" @@ -207,7 +207,7 @@ teardown() { [[ "$output" = "" ]] || false } -@test "dump: SQL type (batch is no-op) - compare tables in database with tables imported file " { +@test "dump: SQL type (batch is no-op) - compare tables in database with tables imported file" { dolt branch new_branch dolt sql -q "CREATE TABLE warehouse(warehouse_id int primary key, warehouse_name longtext);" @@ -520,7 +520,7 @@ SQL [ -f doltdump/warehouse.csv ] } -@test "dump: CSV type - compare tables in database with tables imported from corresponding files " { +@test "dump: CSV type - compare tables in database with tables imported from corresponding files" { create_tables dolt add . @@ -660,7 +660,7 @@ SQL [ -f doltdump/warehouse.json ] } -@test "dump: JSON type - compare tables in database with tables imported from corresponding files " { +@test "dump: JSON type - compare tables in database with tables imported from corresponding files" { create_tables dolt add . diff --git a/integration-tests/bats/export-tables.bats b/integration-tests/bats/export-tables.bats index eee1f02d33..a85aee3184 100644 --- a/integration-tests/bats/export-tables.bats +++ b/integration-tests/bats/export-tables.bats @@ -419,7 +419,9 @@ print(df) table = pq.read_table('dt.parquet') print(table.to_pandas()) " > arrow_test.py + run python3 arrow_test.py + [ "$output" = "$panda_result" ] echo "import pandas as pd diff --git a/integration-tests/bats/log.bats b/integration-tests/bats/log.bats index 772110a643..e44de1f1b0 100755 --- a/integration-tests/bats/log.bats +++ b/integration-tests/bats/log.bats @@ -710,6 +710,7 @@ teardown() { [[ "$output" =~ "invalid --decorate option" ]] || false } +# bats test_tags=no_lambda @test "log: check pager" { skiponwindows "Need to install expect and make this script work on windows." dolt commit --allow-empty -m "commit 1" @@ -747,4 +748,4 @@ teardown() { [[ ! "$output" =~ "HEAD" ]] || false run dolt log commit2 [[ "$output" =~ "HEAD" ]] || false -} \ No newline at end of file +} diff --git a/integration-tests/bats/regression-tests.bats b/integration-tests/bats/regression-tests.bats index 5cfbd79394..354cd9e589 100644 --- a/integration-tests/bats/regression-tests.bats +++ b/integration-tests/bats/regression-tests.bats @@ -52,6 +52,7 @@ SQL [[ "${#lines[@]}" = "2" ]] || false } +# bats test_tags=no_lambda @test "regression-tests: UNIQUE index violations do not break future INSERTs" { skiponwindows "Need to install expect and make this script work on windows." mkdir doltsql diff --git a/integration-tests/bats/sql-diff.bats b/integration-tests/bats/sql-diff.bats index 7c9d0ed52a..37aa0b8f65 100644 --- a/integration-tests/bats/sql-diff.bats +++ b/integration-tests/bats/sql-diff.bats @@ -130,7 +130,7 @@ SQL [ "$output" = "" ] } -@test "sql-diff: output reconciles change to PRIMARY KEY field in row " { +@test "sql-diff: output reconciles change to PRIMARY KEY field in row" { dolt checkout -b firstbranch dolt sql < Date: Tue, 5 Dec 2023 16:50:28 -0800 Subject: [PATCH 41/42] integration-tests/bats/performance.bats: Run some long-running tests locally for now. --- integration-tests/bats/performance.bats | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration-tests/bats/performance.bats b/integration-tests/bats/performance.bats index a3b397b432..de15cc3fd3 100644 --- a/integration-tests/bats/performance.bats +++ b/integration-tests/bats/performance.bats @@ -86,7 +86,7 @@ setup() { BATS_TEST_TIMEOUT=1 } - +# bats test_tags=no_lambda @test "performance: merge with schema change and no conflict" { dolt checkout full dolt checkout -b mod2 @@ -118,6 +118,7 @@ setup() { log_status_eq 0 } +# bats test_tags=no_lambda @test "performance: merge with schema change and conflict" { dolt checkout full dolt checkout -b mod2 From 23c229fa59b5ba48fe4af7fb588463d07eb44037 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Wed, 6 Dec 2023 09:48:04 -0800 Subject: [PATCH 42/42] PR feedback --- go/libraries/events/emitter.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 2eacaaca77..d8df06e976 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -32,6 +32,8 @@ import ( "github.com/dolthub/dolt/go/libraries/utils/iohelp" ) +// Application is the application ID used for all events emitted by this application. Other applications (not dolt) +// should set this once at initialization. var Application = eventsapi.AppID_APP_DOLT // EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below