11package utils
22
33import (
4+ "fmt"
5+ "io"
6+ "net"
7+ "os"
8+ "runtime"
9+ "strings"
10+ "time"
11+
12+ "github.com/ethereum/go-ethereum/log"
413 "github.com/ethereum/go-ethereum/metrics"
5- "github.com/ethereum/go-ethereum/node"
14+ "github.com/ethereum/go-ethereum/metrics/exp"
15+ "github.com/ethereum/go-ethereum/metrics/influxdb"
616 "github.com/optimism-java/shisui2/internal/flags"
717 "github.com/optimism-java/shisui2/portalwire"
818 "github.com/urfave/cli/v2"
@@ -107,7 +117,7 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
107117 PortalRPCPortFlag = & cli.IntFlag {
108118 Name : "rpc.port" ,
109119 Usage : "HTTP-RPC server listening port" ,
110- Value : node . DefaultHTTPPort ,
120+ Value : 8545 ,
111121 Category : flags .PortalNetworkCategory ,
112122 }
113123
@@ -132,24 +142,17 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
132142 Category : flags .PortalNetworkCategory ,
133143 }
134144
135- PortalUDPListenAddrFlag = & cli.StringFlag {
136- Name : "udp.addr" ,
137- Usage : "Protocol UDP server listening interface" ,
138- Value : "" ,
139- Category : flags .PortalNetworkCategory ,
140- }
141-
142145 PortalUDPPortFlag = & cli.IntFlag {
143146 Name : "udp.port" ,
144147 Usage : "Protocol UDP server listening port" ,
145- Value : node . DefaultUDPPort ,
148+ Value : 9009 ,
146149 Category : flags .PortalNetworkCategory ,
147150 }
148151
149152 PortalLogLevelFlag = & cli.IntFlag {
150153 Name : "loglevel" ,
151154 Usage : "Loglevel of portal network" ,
152- Value : node . DefaultLoglevel ,
155+ Value : 3 ,
153156 Category : flags .PortalNetworkCategory ,
154157 }
155158
@@ -178,3 +181,154 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
178181 Value : cli .NewStringSlice (portalwire .History .Name ()),
179182 }
180183)
184+
185+ func SetupMetrics (ctx * cli.Context ) {
186+ if metrics .Enabled {
187+ log .Info ("Enabling metrics collection" )
188+
189+ var (
190+ enableExport = ctx .Bool (MetricsEnableInfluxDBFlag .Name )
191+ enableExportV2 = ctx .Bool (MetricsEnableInfluxDBV2Flag .Name )
192+ )
193+
194+ if enableExport || enableExportV2 {
195+ CheckExclusive (ctx , MetricsEnableInfluxDBFlag , MetricsEnableInfluxDBV2Flag )
196+
197+ v1FlagIsSet := ctx .IsSet (MetricsInfluxDBUsernameFlag .Name ) ||
198+ ctx .IsSet (MetricsInfluxDBPasswordFlag .Name )
199+
200+ v2FlagIsSet := ctx .IsSet (MetricsInfluxDBTokenFlag .Name ) ||
201+ ctx .IsSet (MetricsInfluxDBOrganizationFlag .Name ) ||
202+ ctx .IsSet (MetricsInfluxDBBucketFlag .Name )
203+
204+ if enableExport && v2FlagIsSet {
205+ Fatalf ("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2" )
206+ } else if enableExportV2 && v1FlagIsSet {
207+ Fatalf ("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1" )
208+ }
209+ }
210+
211+ var (
212+ endpoint = ctx .String (MetricsInfluxDBEndpointFlag .Name )
213+ database = ctx .String (MetricsInfluxDBDatabaseFlag .Name )
214+ username = ctx .String (MetricsInfluxDBUsernameFlag .Name )
215+ password = ctx .String (MetricsInfluxDBPasswordFlag .Name )
216+
217+ token = ctx .String (MetricsInfluxDBTokenFlag .Name )
218+ bucket = ctx .String (MetricsInfluxDBBucketFlag .Name )
219+ organization = ctx .String (MetricsInfluxDBOrganizationFlag .Name )
220+ )
221+
222+ if enableExport {
223+ tagsMap := SplitTagsFlag (ctx .String (MetricsInfluxDBTagsFlag .Name ))
224+
225+ log .Info ("Enabling metrics export to InfluxDB" )
226+
227+ go influxdb .InfluxDBWithTags (metrics .DefaultRegistry , 10 * time .Second , endpoint , database , username , password , "geth." , tagsMap )
228+ } else if enableExportV2 {
229+ tagsMap := SplitTagsFlag (ctx .String (MetricsInfluxDBTagsFlag .Name ))
230+
231+ log .Info ("Enabling metrics export to InfluxDB (v2)" )
232+
233+ go influxdb .InfluxDBV2WithTags (metrics .DefaultRegistry , 10 * time .Second , endpoint , token , bucket , organization , "geth." , tagsMap )
234+ }
235+
236+ if ctx .IsSet (MetricsHTTPFlag .Name ) {
237+ address := net .JoinHostPort (ctx .String (MetricsHTTPFlag .Name ), fmt .Sprintf ("%d" , ctx .Int (MetricsPortFlag .Name )))
238+ log .Info ("Enabling stand-alone metrics HTTP endpoint" , "address" , address )
239+ exp .Setup (address )
240+ } else if ctx .IsSet (MetricsPortFlag .Name ) {
241+ log .Warn (fmt .Sprintf ("--%s specified without --%s, metrics server will not start." , MetricsPortFlag .Name , MetricsHTTPFlag .Name ))
242+ }
243+ }
244+ }
245+
246+ // CheckExclusive verifies that only a single instance of the provided flags was
247+ // set by the user. Each flag might optionally be followed by a string type to
248+ // specialize it further.
249+ func CheckExclusive (ctx * cli.Context , args ... interface {}) {
250+ set := make ([]string , 0 , 1 )
251+ for i := 0 ; i < len (args ); i ++ {
252+ // Make sure the next argument is a flag and skip if not set
253+ flag , ok := args [i ].(cli.Flag )
254+ if ! ok {
255+ panic (fmt .Sprintf ("invalid argument, not cli.Flag type: %T" , args [i ]))
256+ }
257+ // Check if next arg extends current and expand its name if so
258+ name := flag .Names ()[0 ]
259+
260+ if i + 1 < len (args ) {
261+ switch option := args [i + 1 ].(type ) {
262+ case string :
263+ // Extended flag check, make sure value set doesn't conflict with passed in option
264+ if ctx .String (flag .Names ()[0 ]) == option {
265+ name += "=" + option
266+ set = append (set , "--" + name )
267+ }
268+ // shift arguments and continue
269+ i ++
270+ continue
271+
272+ case cli.Flag :
273+ default :
274+ panic (fmt .Sprintf ("invalid argument, not cli.Flag or string extension: %T" , args [i + 1 ]))
275+ }
276+ }
277+ // Mark the flag if it's set
278+ if ctx .IsSet (flag .Names ()[0 ]) {
279+ set = append (set , "--" + name )
280+ }
281+ }
282+ if len (set ) > 1 {
283+ Fatalf ("Flags %v can't be used at the same time" , strings .Join (set , ", " ))
284+ }
285+ }
286+
287+ // Fatalf formats a message to standard error and exits the program.
288+ // The message is also printed to standard output if standard error
289+ // is redirected to a different file.
290+ func Fatalf (format string , args ... interface {}) {
291+ w := io .MultiWriter (os .Stdout , os .Stderr )
292+ if runtime .GOOS == "windows" {
293+ // The SameFile check below doesn't work on Windows.
294+ // stdout is unlikely to get redirected though, so just print there.
295+ w = os .Stdout
296+ } else {
297+ outf , _ := os .Stdout .Stat ()
298+ errf , _ := os .Stderr .Stat ()
299+ if outf != nil && errf != nil && os .SameFile (outf , errf ) {
300+ w = os .Stderr
301+ }
302+ }
303+ fmt .Fprintf (w , "Fatal: " + format + "\n " , args ... )
304+ os .Exit (1 )
305+ }
306+
307+ func SplitTagsFlag (tagsFlag string ) map [string ]string {
308+ tags := strings .Split (tagsFlag , "," )
309+ tagsMap := map [string ]string {}
310+
311+ for _ , t := range tags {
312+ if t != "" {
313+ kv := strings .Split (t , "=" )
314+
315+ if len (kv ) == 2 {
316+ tagsMap [kv [0 ]] = kv [1 ]
317+ }
318+ }
319+ }
320+
321+ return tagsMap
322+ }
323+
324+ // SplitAndTrim splits input separated by a comma
325+ // and trims excessive white space from the substrings.
326+ func SplitAndTrim (input string ) (ret []string ) {
327+ l := strings .Split (input , "," )
328+ for _ , r := range l {
329+ if r = strings .TrimSpace (r ); r != "" {
330+ ret = append (ret , r )
331+ }
332+ }
333+ return ret
334+ }
0 commit comments