Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions cmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func dumpCmd(passedExecs execs, cmdConfig *cmdConfiguration) (*cobra.Command, er
// this is the tracer that we will use throughout the entire run
tracer := getTracer("dump")
ctx = util.ContextWithTracer(ctx, tracer)
_, startupSpan := tracer.Start(ctx, "startup")
_, startupSpan := tracer.Start(ctx, string(api.BackupSpanStartup))
cmdConfig.logger.Debug("starting dump")
defer func() {
tp := getTracerProvider()
Expand Down Expand Up @@ -257,36 +257,36 @@ func dumpCmd(passedExecs execs, cmdConfig *cmdConfiguration) (*cobra.Command, er

if err := executor.Timer(timerOpts, func() error {
// start a new span for the dump, should not be a child of the startup one
tracerCtx, dumpSpan := tracer.Start(ctx, "run")
tracerCtx, dumpSpan := tracer.Start(ctx, string(api.BackupSpanRun))
uid := uuid.New()
bytes := int64(0)
exitCode := 0
backupStatus := "ok"
backupStatus := string(api.BackupStatusOK)
attrs := []attribute.KeyValue{
attribute.String("backup.run_id", uid.String()),
attribute.String("db.system", "mysql"),
attribute.String(string(api.BackupAttrRunID), uid.String()),
attribute.String(string(api.BackupAttrDBSystem), "mysql"),
}
if cmdConfig.dbconn != nil {
transport := "tcp"
if strings.HasPrefix(cmdConfig.dbconn.Host, "/") {
transport = "unix"
}
attrs = append(attrs,
attribute.String("network.transport", transport),
attribute.String("server.address", cmdConfig.dbconn.Host),
attribute.String(string(api.BackupAttrNetworkTransport), transport),
attribute.String(string(api.BackupAttrServerAddress), cmdConfig.dbconn.Host),
)
if transport == "tcp" && cmdConfig.dbconn.Port > 0 {
attrs = append(attrs, attribute.Int("server.port", cmdConfig.dbconn.Port))
attrs = append(attrs, attribute.Int(string(api.BackupAttrServerPort), cmdConfig.dbconn.Port))
}
}
dumpSpan.SetAttributes(attrs...)
defer func() {
attrs := []attribute.KeyValue{
attribute.String("backup.status", backupStatus),
attribute.Int("backup.exit_code", exitCode),
attribute.String(string(api.BackupAttrStatus), backupStatus),
attribute.Int(string(api.BackupAttrExitCode), exitCode),
}
if bytes > 0 {
attrs = append(attrs, attribute.Int64("backup.bytes", bytes))
attrs = append(attrs, attribute.Int64(string(api.BackupAttrBytes), bytes))
}
dumpSpan.SetAttributes(attrs...)
dumpSpan.End()
Expand Down Expand Up @@ -315,15 +315,15 @@ func dumpCmd(passedExecs execs, cmdConfig *cmdConfiguration) (*cobra.Command, er
results, err := executor.Dump(tracerCtx, dumpOpts)
if err != nil {
exitCode = 1
backupStatus = "error"
backupStatus = string(api.BackupStatusError)
dumpSpan.SetStatus(codes.Error, fmt.Sprintf("error running dump: %v", err))
return fmt.Errorf("error running dump: %w", err)
}
bytes = results.Bytes
if retention != "" {
if err := executor.Prune(tracerCtx, core.PruneOptions{Targets: targets, Retention: retention, Run: uid}); err != nil {
exitCode = 1
backupStatus = "error"
backupStatus = string(api.BackupStatusError)
dumpSpan.SetStatus(codes.Error, fmt.Sprintf("error running prune: %v", err))
return fmt.Errorf("error running prune: %w", err)
}
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (
filippo.io/age v1.2.1
github.com/InfiniteLoopSpace/go_S-MIME v0.0.0-20181221134359-3f58f9a4b2b6
github.com/bramvdbogaerde/go-scp v1.5.0
github.com/databacker/api/go/api v0.0.0-20260203120843-ea139d59c2ed
github.com/databacker/api/go/api v0.0.0-20260511132103-4edbce2341a3
github.com/gliderlabs/ssh v0.3.8
github.com/google/go-cmp v0.7.0
github.com/kevinburke/ssh_config v1.2.0
Expand All @@ -55,7 +55,7 @@ require (
github.com/containerd/log v0.1.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-chi/chi/v5 v5.2.4 // indirect
github.com/go-chi/chi/v5 v5.2.5 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
Expand All @@ -64,7 +64,7 @@ require (
github.com/moby/sys/atomicwriter v0.1.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/oapi-codegen/runtime v1.1.2 // indirect
github.com/oapi-codegen/runtime v1.4.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
Expand Down
11 changes: 11 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/databacker/api/go/api v0.0.0-20260203120843-ea139d59c2ed h1:PKzk3NUbJGSOpINtzGNSJR8jLqrTIy0enpaUma5RFgk=
github.com/databacker/api/go/api v0.0.0-20260203120843-ea139d59c2ed/go.mod h1:vXp1gX/diWXW659asaBZ7K3Wgs2OG3igz0dF0UB4yIY=
github.com/databacker/api/go/api v0.0.0-20260511123027-25b8d0ecddb7 h1:wAl574i+9CD/SJLh7ng8NuGMGa04VCFPeoxqk9wFRFE=
github.com/databacker/api/go/api v0.0.0-20260511123027-25b8d0ecddb7/go.mod h1:vXp1gX/diWXW659asaBZ7K3Wgs2OG3igz0dF0UB4yIY=
github.com/databacker/api/go/api v0.0.0-20260511131506-50108473a7ba h1:vMkvDnSGi3QzJPSs9zEowfUHSt2U2nXgWmSZafLzRyw=
github.com/databacker/api/go/api v0.0.0-20260511131506-50108473a7ba/go.mod h1:vXp1gX/diWXW659asaBZ7K3Wgs2OG3igz0dF0UB4yIY=
github.com/databacker/api/go/api v0.0.0-20260511132103-4edbce2341a3 h1:SVRt6Uqajczc09iEGcax2AhL16dYrvcjanX81TcWROM=
github.com/databacker/api/go/api v0.0.0-20260511132103-4edbce2341a3/go.mod h1:vXp1gX/diWXW659asaBZ7K3Wgs2OG3igz0dF0UB4yIY=
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=
Expand Down Expand Up @@ -118,6 +124,8 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
Expand Down Expand Up @@ -220,6 +228,8 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oapi-codegen/runtime v1.1.2 h1:P2+CubHq8fO4Q6fV1tqDBZHCwpVpvPg7oKiYzQgXIyI=
github.com/oapi-codegen/runtime v1.1.2/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/oapi-codegen/runtime v1.4.0 h1:KLOSFOp7UzkbS7Cs1ms6NBEKYr0WmH2wZG0KKbd2er4=
github.com/oapi-codegen/runtime v1.4.0/go.mod h1:5sw5fxCDmnOzKNYmkVNF8d34kyUeejJEY8HNT2WaPec=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
Expand Down Expand Up @@ -434,6 +444,7 @@ golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
34 changes: 22 additions & 12 deletions pkg/core/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"

"github.com/databacker/api/go/api"
"github.com/databacker/mysql-backup/pkg/archive"
"github.com/databacker/mysql-backup/pkg/database"
"github.com/databacker/mysql-backup/pkg/util"
Expand All @@ -23,7 +24,7 @@ import (
func (e *Executor) Dump(ctx context.Context, opts DumpOptions) (DumpResults, error) {
results := DumpResults{Start: time.Now()}
tracer := util.GetTracerFromContext(ctx)
ctx, span := tracer.Start(ctx, "dump")
ctx, span := tracer.Start(ctx, string(api.BackupSpanDump))
defer func() {
results.End = time.Now()
span.End()
Expand Down Expand Up @@ -55,7 +56,7 @@ func (e *Executor) Dump(ctx context.Context, opts DumpOptions) (DumpResults, err
timepart = strings.ReplaceAll(timepart, ":", "-")
}
results.Timestamp = timepart
span.SetAttributes(attribute.String("timestamp", timepart))
span.SetAttributes(attribute.String(string(api.BackupAttrTimestamp), timepart))

// sourceFilename: file that the uploader looks for when performing the upload
// targetFilename: the remote file that is actually uploaded
Expand All @@ -64,7 +65,7 @@ func (e *Executor) Dump(ctx context.Context, opts DumpOptions) (DumpResults, err
if err != nil {
return results, fmt.Errorf("failed to process filename pattern: %v", err)
}
span.SetAttributes(attribute.String("source-filename", sourceFilename), attribute.String("target-filename", targetFilename))
span.SetAttributes(attribute.String(string(api.BackupAttrSourceFilename), sourceFilename), attribute.String(string(api.BackupAttrTargetFilename), targetFilename))

// create a temporary working directory
tmpdir, err := os.MkdirTemp("", "databacker_backup")
Expand All @@ -87,15 +88,15 @@ func (e *Executor) Dump(ctx context.Context, opts DumpOptions) (DumpResults, err
dw := make([]database.DumpWriter, 0)

// do we back up all schemas, or just provided ones
span.SetAttributes(attribute.Bool("provided-schemas", len(dbnames) != 0))
span.SetAttributes(attribute.Bool(string(api.BackupAttrProvidedSchemas), len(dbnames) != 0))
if len(dbnames) == 0 {
if dbnames, err = database.GetSchemas(dbconn); err != nil {
return results, fmt.Errorf("failed to list database schemas: %v", err)
}
}
// filter out excluded databases
dbnames = filterExcludedDatabases(dbnames, opts.Exclude)
span.SetAttributes(attribute.StringSlice("actual-schemas", dbnames))
span.SetAttributes(attribute.StringSlice(string(api.BackupAttrActualSchemas), dbnames))
for _, s := range dbnames {
outFile := path.Join(workdir, fmt.Sprintf("%s_%s.sql", s, timepart))
f, err := os.Create(outFile)
Expand All @@ -108,7 +109,7 @@ func (e *Executor) Dump(ctx context.Context, opts DumpOptions) (DumpResults, err
})
}
results.DumpStart = time.Now()
dbDumpCtx, dbDumpSpan := tracer.Start(ctx, "database_dump")
dbDumpCtx, dbDumpSpan := tracer.Start(ctx, string(api.BackupSpanDatabaseDump))
if err := database.Dump(dbDumpCtx, dbconn, database.DumpOpts{
Compact: compact,
Triggers: triggers,
Expand All @@ -130,7 +131,7 @@ func (e *Executor) Dump(ctx context.Context, opts DumpOptions) (DumpResults, err

// create my tar writer to archive it all together
// WRONG: THIS WILL CAUSE IT TO TRY TO LOOP BACK ON ITSELF
_, tarSpan := tracer.Start(ctx, "output_tar")
_, tarSpan := tracer.Start(ctx, string(api.BackupSpanOutputTar))
outFile := path.Join(tmpdir, sourceFilename)
f, err := os.OpenFile(outFile, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
Expand Down Expand Up @@ -173,7 +174,7 @@ func (e *Executor) Dump(ctx context.Context, opts DumpOptions) (DumpResults, err
}
if info, err := os.Stat(outFile); err == nil {
results.Bytes = info.Size()
tarSpan.SetAttributes(attribute.Int64("bytes", results.Bytes))
tarSpan.SetAttributes(attribute.Int64(string(api.BackupAttrBytes), results.Bytes))
}
tarSpan.SetStatus(codes.Ok, "completed")
tarSpan.End()
Expand All @@ -184,18 +185,27 @@ func (e *Executor) Dump(ctx context.Context, opts DumpOptions) (DumpResults, err
}

// upload to each destination
uploadCtx, uploadSpan := tracer.Start(ctx, "upload")
uploadCtx, uploadSpan := tracer.Start(ctx, string(api.BackupSpanUpload))
for _, t := range targets {
targetCtx, targetSpan := tracer.Start(uploadCtx, string(api.BackupSpanUpload))
targetSpan.SetAttributes(
attribute.String(string(api.BackupAttrTargetType), t.Protocol()),
attribute.String(string(api.BackupAttrTargetURL), t.URL()),
)
uploadResult := UploadResult{Target: t.URL(), Start: time.Now()}
targetCleanFilename := t.Clean(targetFilename)
logger.Debugf("uploading via protocol %s from %s to %s", t.Protocol(), sourceFilename, targetCleanFilename)
copied, err := t.Push(uploadCtx, targetCleanFilename, filepath.Join(tmpdir, sourceFilename), logger)
copied, err := t.Push(targetCtx, targetCleanFilename, filepath.Join(tmpdir, sourceFilename), logger)
if err != nil {
targetSpan.SetStatus(codes.Error, err.Error())
targetSpan.End()
uploadSpan.SetStatus(codes.Error, err.Error())
uploadSpan.End()
return results, fmt.Errorf("failed to push file: %v", err)
}
logger.Debugf("completed copying %d bytes", copied)
targetSpan.SetStatus(codes.Ok, "completed")
targetSpan.End()
uploadResult.Filename = targetCleanFilename
uploadResult.End = time.Now()
results.Uploads = append(results.Uploads, uploadResult)
Expand All @@ -217,7 +227,7 @@ func preBackup(ctx context.Context, timestamp, dumpfile, dumpdir, preBackupDir s
"DUMPDIR": dumpdir,
"DB_DEBUG": fmt.Sprintf("%v", debug),
}
ctx, span := util.GetTracerFromContext(ctx).Start(ctx, "pre-backup")
ctx, span := util.GetTracerFromContext(ctx).Start(ctx, string(api.BackupSpanPreBackup))
defer span.End()
return runScripts(ctx, preBackupDir, env)
}
Expand All @@ -230,7 +240,7 @@ func postBackup(ctx context.Context, timestamp, dumpfile, dumpdir, postBackupDir
"DUMPDIR": dumpdir,
"DB_DEBUG": fmt.Sprintf("%v", debug),
}
ctx, span := util.GetTracerFromContext(ctx).Start(ctx, "post-backup")
ctx, span := util.GetTracerFromContext(ctx).Start(ctx, string(api.BackupSpanPostBackup))
defer span.End()
return runScripts(ctx, postBackupDir, env)
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/core/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strconv"
"time"

"github.com/databacker/api/go/api"
"github.com/databacker/mysql-backup/pkg/storage"
"github.com/databacker/mysql-backup/pkg/util"
"github.com/sirupsen/logrus"
Expand All @@ -23,7 +24,7 @@ var filenameRE = regexp.MustCompile(`^db_backup_(\d{4})-(\d{2})-(\d{2})T(\d{2})[
// Prune prune older backups
func (e *Executor) Prune(ctx context.Context, opts PruneOptions) error {
tracer := util.GetTracerFromContext(ctx)
tracerCtx, span := tracer.Start(ctx, "prune")
tracerCtx, span := tracer.Start(ctx, string(api.BackupSpanPrune))
defer span.End()
logger := e.Logger.WithField("run", opts.Run.String())
logger.Level = e.Logger.Level
Expand Down Expand Up @@ -59,7 +60,7 @@ func pruneTarget(ctx context.Context, logger *logrus.Entry, target storage.Stora
pruned int
candidates, ignored, invalidDate []string
)
ctx, span := util.GetTracerFromContext(ctx).Start(ctx, fmt.Sprintf("pruneTarget %s", target.URL()))
ctx, span := util.GetTracerFromContext(ctx).Start(ctx, fmt.Sprintf("%s %s", string(api.BackupSpanPruneTarget), target.URL()))
defer span.End()

logger.Debugf("pruning target %s", target.URL())
Expand Down Expand Up @@ -138,7 +139,7 @@ func pruneTarget(ctx context.Context, logger *logrus.Entry, target storage.Stora
}

// we have the list, remove them all
span.SetAttributes(attribute.StringSlice("candidates", candidates), attribute.StringSlice("ignored", ignored), attribute.StringSlice("invalidDate", invalidDate))
span.SetAttributes(attribute.StringSlice(string(api.BackupAttrCandidates), candidates), attribute.StringSlice(string(api.BackupAttrIgnored), ignored), attribute.StringSlice(string(api.BackupAttrInvalidDate), invalidDate))
for _, filename := range candidates {
if err := target.Remove(ctx, filename, logger); err != nil {
return fmt.Errorf("failed to remove file %s: %v", filename, err)
Expand Down
Loading
Loading