main.go (81 lines of code) (raw):

package main import ( "context" "flag" "fmt" "os" "os/signal" "syscall" "time" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/oklog/oklog/pkg/group" "github.com/prometheus/tsdb" ) func main() { v1Path := flag.String("v1-path", "./data-v1", "Path to the v1 storage directory.") v2Path := flag.String("v2-path", "./data-v2", "Path to the v2 storage directory.") lookback := flag.Duration("lookback", 15*24*time.Hour, "How far back to start when exporting old data.") step := flag.Duration("step", 15*time.Minute, "How much data to load at once.") parallelism := flag.Int("parallelism", 1, "How many series to migrate at the same time.") skipUnknownLabels := flag.Bool("skip-unknown-labels", false, "Skip unknown metrics/labels instead of failing migration.") flag.Parse() logger := log.NewSyncLogger(log.NewLogfmtLogger(os.Stderr)) if *parallelism < 1 { level.Error(logger).Log("err", "-parallelism must be set to at least 1") os.Exit(1) } v2Storage, err := tsdb.Open(*v2Path, logger, nil, &tsdb.Options{ RetentionDuration: 999999 * 24 * 60 * 60 * 1000, BlockRanges: []int64{2 * 60 * 60 * 1000}, }) if err != nil { level.Error(logger).Log("msg", "error starting v2 storage", "err", err) os.Exit(1) } defer v2Storage.Close() migrator := storageMigrator{ v1Path: *v1Path, v2Storage: v2Storage, parallelism: *parallelism, skipUnknownLabels: *skipUnknownLabels, } var g group.Group { // Interrupt handler. term := make(chan os.Signal) signal.Notify(term, os.Interrupt, syscall.SIGTERM) cancel := make(chan struct{}) g.Add( func() error { select { case <-term: level.Warn(logger).Log("msg", "received SIGTERM, exiting gracefully...") case <-cancel: break } return nil }, func(err error) { close(cancel) }, ) } { // Migrator. ctx, cancel := context.WithCancel(context.Background()) g.Add( func() error { if err := migrator.migrate(ctx, *lookback, *step); err != nil { return fmt.Errorf("error migrating storage: %s", err) } return nil }, func(err error) { cancel() }, ) } if err := g.Run(); err != nil { level.Error(logger).Log("err", err) } level.Info(logger).Log("msg", "Done.") }