]> Sergey Matveev's repositories - btrtrc.git/blob - cmd/torrent/main.go
cmd/torrent: Time and log TracerProvider.Shutdown
[btrtrc.git] / cmd / torrent / main.go
1 // Downloads torrents from the command-line.
2 package main
3
4 import (
5         "context"
6         "fmt"
7         stdLog "log"
8         "net/http"
9         "time"
10
11         "github.com/prometheus/client_golang/prometheus"
12         "github.com/prometheus/client_golang/prometheus/promhttp"
13         "go.opentelemetry.io/otel"
14         "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
15         "go.opentelemetry.io/otel/sdk/trace"
16
17         "github.com/anacrolix/bargle"
18         "github.com/anacrolix/envpprof"
19         "github.com/anacrolix/log"
20         xprometheus "github.com/anacrolix/missinggo/v2/prometheus"
21
22         "github.com/anacrolix/torrent/version"
23 )
24
25 func init() {
26         prometheus.MustRegister(xprometheus.NewExpvarCollector())
27         http.Handle("/metrics", promhttp.Handler())
28 }
29
30 func shutdownTracerProvider(ctx context.Context, tp *trace.TracerProvider) {
31         started := time.Now()
32         err := tp.Shutdown(ctx)
33         elapsed := time.Since(started)
34         log.Levelf(log.Error, "shutting down tracer provider (took %v): %v", elapsed, err)
35 }
36
37 func main() {
38         defer stdLog.SetFlags(stdLog.Flags() | stdLog.Lshortfile)
39
40         ctx := context.Background()
41         tracingExporter, err := otlptracegrpc.New(ctx)
42         if err != nil {
43                 log.Fatalf("creating tracing exporter: %v", err)
44         }
45         tracerProvider := trace.NewTracerProvider(trace.WithBatcher(tracingExporter))
46         defer shutdownTracerProvider(ctx, tracerProvider)
47         otel.SetTracerProvider(tracerProvider)
48
49         main := bargle.Main{}
50         main.Defer(envpprof.Stop)
51         main.Defer(func() { shutdownTracerProvider(ctx, tracerProvider) })
52         debug := false
53         debugFlag := bargle.NewFlag(&debug)
54         debugFlag.AddLong("debug")
55         main.Options = append(main.Options, debugFlag.Make())
56         main.Positionals = append(main.Positionals,
57                 bargle.Subcommand{Name: "metainfo", Command: metainfoCmd()},
58                 //bargle.Subcommand{Name: "announce", Command: func() bargle.Command {
59                 //      var cmd AnnounceCmd
60                 //      err := p.NewParser().AddParams(
61                 //              args.Pos("tracker", &cmd.Tracker),
62                 //              args.Pos("infohash", &cmd.InfoHash)).Parse()
63                 //      if err != nil {
64                 //              return err
65                 //      }
66                 //      return announceErr(cmd)
67                 //}()},
68                 bargle.Subcommand{Name: "scrape", Command: func() bargle.Command {
69                         var scrapeCfg scrapeCfg
70                         cmd := bargle.FromStruct(&scrapeCfg)
71                         cmd.Desc = "fetch swarm metrics for info-hashes from tracker"
72                         cmd.DefaultAction = func() error {
73                                 return scrape(scrapeCfg)
74                         }
75                         return cmd
76                 }()},
77                 bargle.Subcommand{Name: "download", Command: func() bargle.Command {
78                         var dlc DownloadCmd
79                         cmd := bargle.FromStruct(&dlc)
80                         cmd.DefaultAction = func() error {
81                                 return downloadErr(downloadFlags{
82                                         Debug:       debug,
83                                         DownloadCmd: dlc,
84                                 })
85                         }
86                         return cmd
87                 }()},
88                 //bargle.Subcommand{Name:
89                 //      "bencode", Command: func() bargle.Command {
90                 //              var print func(interface{}) error
91                 //              if !p.Parse(
92                 //                      args.Subcommand("json", func(ctx args.SubCmdCtx) (err error) {
93                 //                              ctx.Parse()
94                 //                              je := json.NewEncoder(os.Stdout)
95                 //                              je.SetIndent("", "  ")
96                 //                              print = je.Encode
97                 //                              return nil
98                 //                      }),
99                 //                      args.Subcommand("spew", func(ctx args.SubCmdCtx) (err error) {
100                 //                              ctx.Parse()
101                 //                              config := spew.NewDefaultConfig()
102                 //                              config.DisableCapacities = true
103                 //                              config.Indent = "  "
104                 //                              print = func(v interface{}) error {
105                 //                                      config.Dump(v)
106                 //                                      return nil
107                 //                              }
108                 //                              return nil
109                 //                      }),
110                 //              ).RanSubCmd {
111                 //                      return errors.New("an output type is required")
112                 //              }
113                 //              d := bencode.NewDecoder(os.Stdin)
114                 //              p.Defer(func() error {
115                 //                      for i := 0; ; i++ {
116                 //                              var v interface{}
117                 //                              err := d.Decode(&v)
118                 //                              if err == io.EOF {
119                 //                                      break
120                 //                              }
121                 //                              if err != nil {
122                 //                                      return fmt.Errorf("decoding message index %d: %w", i, err)
123                 //                              }
124                 //                              print(v)
125                 //                      }
126                 //                      return nil
127                 //              })
128                 //              return nil
129                 //      }(),
130                 //      Desc: "reads bencoding from stdin into Go native types and spews the result",
131                 //},
132                 bargle.Subcommand{Name: "version", Command: bargle.Command{
133                         DefaultAction: func() error {
134                                 fmt.Printf("HTTP User-Agent: %q\n", version.DefaultHttpUserAgent)
135                                 fmt.Printf("Torrent client version: %q\n", version.DefaultExtendedHandshakeClientVersion)
136                                 fmt.Printf("Torrent version prefix: %q\n", version.DefaultBep20Prefix)
137                                 return nil
138                         },
139                         Desc: "prints various protocol default version strings",
140                 }},
141                 bargle.Subcommand{Name: "serve", Command: serve()},
142                 bargle.Subcommand{Name: "create", Command: create()},
143         )
144         main.Run()
145 }