github.com/sunriselayer/sunrise-da@v0.13.1-sr3/cmd/flags_misc.go (about) 1 package cmd 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "net/http/pprof" 8 "strings" 9 10 otelpyroscope "github.com/grafana/otel-profiling-go" 11 logging "github.com/ipfs/go-log/v2" 12 "github.com/spf13/cobra" 13 flag "github.com/spf13/pflag" 14 "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" 15 "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" 16 17 "github.com/sunriselayer/sunrise-da/logs" 18 "github.com/sunriselayer/sunrise-da/nodebuilder" 19 modp2p "github.com/sunriselayer/sunrise-da/nodebuilder/p2p" 20 ) 21 22 var ( 23 LogLevelFlag = "log.level" 24 LogLevelModuleFlag = "log.level.module" 25 pprofFlag = "pprof" 26 tracingFlag = "tracing" 27 tracingEndpointFlag = "tracing.endpoint" 28 tracingTlS = "tracing.tls" 29 metricsFlag = "metrics" 30 metricsEndpointFlag = "metrics.endpoint" 31 metricsTlS = "metrics.tls" 32 p2pMetrics = "p2p.metrics" 33 pyroscopeFlag = "pyroscope" 34 pyroscopeTracing = "pyroscope.tracing" 35 pyroscopeEndpoint = "pyroscope.endpoint" 36 ) 37 38 // MiscFlags gives a set of hardcoded miscellaneous flags. 39 func MiscFlags() *flag.FlagSet { 40 flags := &flag.FlagSet{} 41 42 flags.String( 43 LogLevelFlag, 44 "INFO", 45 `DEBUG, INFO, WARN, ERROR, DPANIC, PANIC, FATAL 46 and their lower-case forms`, 47 ) 48 49 flags.StringSlice( 50 LogLevelModuleFlag, 51 nil, 52 "<module>:<level>, e.g. pubsub:debug", 53 ) 54 55 flags.Bool( 56 pprofFlag, 57 false, 58 "Enables standard profiling handler (pprof) and exposes the profiles on port 6000", 59 ) 60 61 flags.Bool( 62 tracingFlag, 63 false, 64 "Enables OTLP tracing with HTTP exporter", 65 ) 66 67 flags.String( 68 tracingEndpointFlag, 69 "localhost:4318", 70 "Sets HTTP endpoint for OTLP traces to be exported to. Depends on '--tracing'", 71 ) 72 73 flags.Bool( 74 tracingTlS, 75 true, 76 "Enable TLS connection to OTLP tracing backend", 77 ) 78 79 flags.Bool( 80 metricsFlag, 81 false, 82 "Enables OTLP metrics with HTTP exporter", 83 ) 84 85 flags.String( 86 metricsEndpointFlag, 87 "localhost:4318", 88 "Sets HTTP endpoint for OTLP metrics to be exported to. Depends on '--metrics'", 89 ) 90 91 flags.Bool( 92 metricsTlS, 93 true, 94 "Enable TLS connection to OTLP metric backend", 95 ) 96 97 flags.Bool( 98 p2pMetrics, 99 false, 100 "Enable libp2p metrics", 101 ) 102 103 flags.Bool( 104 pyroscopeFlag, 105 false, 106 "Enables Pyroscope profiling", 107 ) 108 109 flags.Bool( 110 pyroscopeTracing, 111 false, 112 "Enables Pyroscope tracing integration. Depends on --tracing", 113 ) 114 115 flags.String( 116 pyroscopeEndpoint, 117 "http://localhost:4040", 118 "Sets HTTP endpoint for Pyroscope profiles to be exported to. Depends on '--pyroscope'", 119 ) 120 121 return flags 122 } 123 124 // ParseMiscFlags parses miscellaneous flags from the given cmd and applies values to Env. 125 func ParseMiscFlags(ctx context.Context, cmd *cobra.Command) (context.Context, error) { 126 logLevel := cmd.Flag(LogLevelFlag).Value.String() 127 if logLevel != "" { 128 level, err := logging.LevelFromString(logLevel) 129 if err != nil { 130 return ctx, fmt.Errorf("cmd: while parsing '%s': %w", LogLevelFlag, err) 131 } 132 133 logs.SetAllLoggers(level) 134 } 135 136 logModules, err := cmd.Flags().GetStringSlice(LogLevelModuleFlag) 137 if err != nil { 138 panic(err) 139 } 140 for _, ll := range logModules { 141 params := strings.Split(ll, ":") 142 if len(params) != 2 { 143 return ctx, fmt.Errorf("cmd: %s arg must be in form <module>:<level>, e.g. pubsub:debug", LogLevelModuleFlag) 144 } 145 146 err := logging.SetLogLevel(params[0], params[1]) 147 if err != nil { 148 return ctx, err 149 } 150 } 151 152 ok, err := cmd.Flags().GetBool(pprofFlag) 153 if err != nil { 154 panic(err) 155 } 156 157 if ok { 158 // TODO(@Wondertan): Eventually, this should be registered on http server in RPC 159 // by passing the http.Server with preregistered pprof handlers to the node. 160 // Node should not register pprof itself. 161 go func() { 162 mux := http.NewServeMux() 163 mux.HandleFunc("/debug/pprof/", pprof.Index) 164 mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) 165 mux.HandleFunc("/debug/pprof/profile", pprof.Profile) 166 mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) 167 mux.HandleFunc("/debug/pprof/trace", pprof.Trace) 168 err := http.ListenAndServe("0.0.0.0:6000", mux) //nolint:gosec 169 if err != nil { 170 log.Fatalw("failed to start pprof server", "err", err) 171 } else { 172 log.Info("started pprof server on port 6000") 173 } 174 }() 175 } 176 177 ok, err = cmd.Flags().GetBool(pyroscopeFlag) 178 if err != nil { 179 panic(err) 180 } 181 182 if ok { 183 ctx = WithNodeOptions(ctx, 184 nodebuilder.WithPyroscope( 185 cmd.Flag(pyroscopeEndpoint).Value.String(), 186 NodeType(ctx), 187 ), 188 ) 189 } 190 191 ok, err = cmd.Flags().GetBool(tracingFlag) 192 if err != nil { 193 panic(err) 194 } 195 196 if ok { 197 opts := []otlptracehttp.Option{ 198 otlptracehttp.WithCompression(otlptracehttp.GzipCompression), 199 otlptracehttp.WithEndpoint(cmd.Flag(tracingEndpointFlag).Value.String()), 200 } 201 if ok, err := cmd.Flags().GetBool(tracingTlS); err != nil { 202 panic(err) 203 } else if !ok { 204 opts = append(opts, otlptracehttp.WithInsecure()) 205 } 206 207 pyroOpts := make([]otelpyroscope.Option, 0) 208 ok, err = cmd.Flags().GetBool(pyroscopeTracing) 209 if err != nil { 210 panic(err) 211 } 212 if ok { 213 pyroOpts = append(pyroOpts, 214 otelpyroscope.WithAppName("sunrise.da-node"), 215 otelpyroscope.WithPyroscopeURL(cmd.Flag(pyroscopeEndpoint).Value.String()), 216 otelpyroscope.WithRootSpanOnly(true), 217 otelpyroscope.WithAddSpanName(true), 218 otelpyroscope.WithProfileURL(true), 219 otelpyroscope.WithProfileBaselineURL(true), 220 ) 221 } 222 ctx = WithNodeOptions(ctx, nodebuilder.WithTraces(opts, pyroOpts)) 223 } 224 225 ok, err = cmd.Flags().GetBool(metricsFlag) 226 if err != nil { 227 panic(err) 228 } 229 230 if ok { 231 opts := []otlpmetrichttp.Option{ 232 otlpmetrichttp.WithCompression(otlpmetrichttp.GzipCompression), 233 otlpmetrichttp.WithEndpoint(cmd.Flag(metricsEndpointFlag).Value.String()), 234 } 235 if ok, err := cmd.Flags().GetBool(metricsTlS); err != nil { 236 panic(err) 237 } else if !ok { 238 opts = append(opts, otlpmetrichttp.WithInsecure()) 239 } 240 241 ctx = WithNodeOptions(ctx, nodebuilder.WithMetrics(opts, NodeType(ctx))) 242 } 243 244 ok, err = cmd.Flags().GetBool(p2pMetrics) 245 if err != nil { 246 panic(err) 247 } 248 249 if ok { 250 if metricsEnabled, _ := cmd.Flags().GetBool(metricsFlag); !metricsEnabled { 251 log.Error("--p2p.metrics used without --metrics being enabled") 252 } else { 253 ctx = WithNodeOptions(ctx, modp2p.WithMetrics()) 254 } 255 } 256 257 return ctx, err 258 }