diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 0e7b5ea536..c9265dd5ca 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -50,12 +50,8 @@ jobs: - name: Build Binary for ARM if: matrix.os == 'ubuntu-18.04' - env: - GOPATH: /home/runner/work/woodpecker/go run: | - mkdir -p $GOPATH/src/github.com/bnb-chain/bsc/ - cp -r ./* $GOPATH/src/github.com/bnb-chain/bsc/ - cd $GOPATH/src/github.com/bnb-chain/bsc/ && make geth-linux-arm + make geth-linux-arm # ============================== # Upload artifacts # ============================== @@ -86,28 +82,28 @@ jobs: if: matrix.os == 'ubuntu-18.04' with: name: arm5 - path: /home/runner/work/woodpecker/go/src/github.com/bnb-chain/bsc/build/bin/geth-linux-arm-5 + path: ./build/bin/geth-linux-arm-5 - name: Upload ARM-6 Build uses: actions/upload-artifact@v2 if: matrix.os == 'ubuntu-18.04' with: name: arm6 - path: /home/runner/work/woodpecker/go/src/github.com/bnb-chain/bsc/build/bin/geth-linux-arm-6 + path: ./build/bin/geth-linux-arm-6 - name: Upload ARM-7 Build uses: actions/upload-artifact@v2 if: matrix.os == 'ubuntu-18.04' with: name: arm7 - path: /home/runner/work/woodpecker/go/src/github.com/bnb-chain/bsc/build/bin/geth-linux-arm-7 + path: ./build/bin/geth-linux-arm-7 - name: Upload ARM-64 Build uses: actions/upload-artifact@v2 if: matrix.os == 'ubuntu-18.04' with: name: arm64 - path: /home/runner/work/woodpecker/go/src/github.com/bnb-chain/bsc/build/bin/geth-linux-arm64 + path: ./build/bin/geth-linux-arm64 release: name: Release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 11c5f78939..778d8a56f5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,12 +51,8 @@ jobs: - name: Build Binary for ARM if: matrix.os == 'ubuntu-18.04' - env: - GOPATH: /home/runner/work/woodpecker/go run: | - mkdir -p $GOPATH/src/github.com/bnb-chain/bsc/ - cp -r ./* $GOPATH/src/github.com/bnb-chain/bsc/ - cd $GOPATH/src/github.com/bnb-chain/bsc/ && make geth-linux-arm + make geth-linux-arm # ============================== # Upload artifacts # ============================== @@ -87,28 +83,28 @@ jobs: if: matrix.os == 'ubuntu-18.04' with: name: arm5 - path: /home/runner/work/woodpecker/go/src/github.com/bnb-chain/bsc/build/bin/geth-linux-arm-5 + path: ./build/bin/geth-linux-arm-5 - name: Upload ARM-6 Build uses: actions/upload-artifact@v2 if: matrix.os == 'ubuntu-18.04' with: name: arm6 - path: /home/runner/work/woodpecker/go/src/github.com/bnb-chain/bsc/build/bin/geth-linux-arm-6 + path: ./build/bin/geth-linux-arm-6 - name: Upload ARM-7 Build uses: actions/upload-artifact@v2 if: matrix.os == 'ubuntu-18.04' with: name: arm7 - path: /home/runner/work/woodpecker/go/src/github.com/bnb-chain/bsc/build/bin/geth-linux-arm-7 + path: ./build/bin/geth-linux-arm-7 - name: Upload ARM-64 Build uses: actions/upload-artifact@v2 if: matrix.os == 'ubuntu-18.04' with: name: arm64 - path: /home/runner/work/woodpecker/go/src/github.com/bnb-chain/bsc/build/bin/geth-linux-arm64 + path: ./build/bin/geth-linux-arm64 release: name: Release diff --git a/Makefile b/Makefile index d2e5d66fdc..b35a4a9e4d 100644 --- a/Makefile +++ b/Makefile @@ -9,25 +9,30 @@ GOBIN = ./build/bin GO ?= latest GORUN = env GO111MODULE=on go run +GIT_COMMIT=$(shell git rev-parse HEAD) +GIT_COMMIT_DATE=$(shell git log -n1 --pretty='format:%cd' --date=format:'%Y%m%d') geth: $(GORUN) build/ci.go install ./cmd/geth @echo "Done building." @echo "Run \"$(GOBIN)/geth\" to launch geth." +ldflags = -X main.gitCommit=$(GIT_COMMIT) \ + -X main.gitDate=$(GIT_COMMIT_DATE) + geth-linux-arm: geth-linux-arm5 geth-linux-arm6 geth-linux-arm7 geth-linux-arm64 geth-linux-arm5: - env GO111MODULE=on GOARCH=arm GOARM=5 GOOS=linux go build -o build/bin/geth-linux-arm-5 ./cmd/geth + env GO111MODULE=on GOARCH=arm GOARM=5 GOOS=linux go build -ldflags="$(ldflags)" -o build/bin/geth-linux-arm-5 ./cmd/geth geth-linux-arm6: - env GO111MODULE=on GOARCH=arm GOARM=6 GOOS=linux go build -o build/bin/geth-linux-arm-6 ./cmd/geth + env GO111MODULE=on GOARCH=arm GOARM=6 GOOS=linux go build -ldflags="$(ldflags)" -o build/bin/geth-linux-arm-6 ./cmd/geth geth-linux-arm7: - env GO111MODULE=on GOARCH=arm GOARM=7 GOOS=linux go build -o build/bin/geth-linux-arm-7 ./cmd/geth + env GO111MODULE=on GOARCH=arm GOARM=7 GOOS=linux go build -ldflags="$(ldflags)" -o build/bin/geth-linux-arm-7 ./cmd/geth geth-linux-arm64: - env GO111MODULE=on GOARCH=arm64 GOOS=linux go build -o build/bin/geth-linux-arm64 ./cmd/geth + env GO111MODULE=on GOARCH=arm64 GOOS=linux go build -ldflags="$(ldflags)" -o build/bin/geth-linux-arm64 ./cmd/geth all: $(GORUN) build/ci.go install diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 9ed921c24f..a4455c3c0f 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -324,7 +324,7 @@ func prepare(ctx *cli.Context) { } // Start metrics export if enabled - utils.SetupMetrics(ctx) + utils.SetupMetrics(ctx, utils.EnableBuildInfo(gitCommit, gitDate)) // Start system runtime metrics collection go metrics.CollectProcessMetrics(3 * time.Second) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index cb6741bace..33cc72bb27 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -26,6 +26,7 @@ import ( "math/big" "os" "path/filepath" + "runtime" godebug "runtime/debug" "strconv" "strings" @@ -1931,7 +1932,23 @@ func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, cfg node.C } } -func SetupMetrics(ctx *cli.Context) { +type SetupMetricsOption func() + +func EnableBuildInfo(gitCommit, gitDate string) SetupMetricsOption { + return func() { + // register build info into metrics + metrics.NewRegisteredLabel("build-info", nil).Mark(map[string]interface{}{ + "version": params.VersionWithMeta, + "git-commit": gitCommit, + "git-commit-date": gitDate, + "go-version": runtime.Version(), + "operating-system": runtime.GOOS, + "architecture": runtime.GOARCH, + }) + } +} + +func SetupMetrics(ctx *cli.Context, options ...SetupMetricsOption) { if metrics.Enabled { log.Info("Enabling metrics collection") @@ -1987,6 +2004,10 @@ func SetupMetrics(ctx *cli.Context) { log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address) exp.Setup(address) } + + for _, opt := range options { + opt() + } } } diff --git a/metrics/exp/exp.go b/metrics/exp/exp.go index 3ebe8cc68a..4d9304a5f6 100644 --- a/metrics/exp/exp.go +++ b/metrics/exp/exp.go @@ -95,6 +95,20 @@ func (exp *exp) getFloat(name string) *expvar.Float { return v } +func (exp *exp) getMap(name string) *expvar.Map { + var v *expvar.Map + exp.expvarLock.Lock() + p := expvar.Get(name) + if p != nil { + v = p.(*expvar.Map) + } else { + v = new(expvar.Map) + expvar.Publish(name, v) + } + exp.expvarLock.Unlock() + return v +} + func (exp *exp) publishCounter(name string, metric metrics.Counter) { v := exp.getInt(name) v.Set(metric.Count()) @@ -162,6 +176,60 @@ func (exp *exp) publishResettingTimer(name string, metric metrics.ResettingTimer exp.getInt(name + ".99-percentile").Set(ps[3]) } +func (exp *exp) publishLabel(name string, metric metrics.Label) { + labels := metric.Value() + for k, v := range labels { + exp.getMap(name).Set(k, exp.interfaceToExpVal(v)) + } +} + +func (exp *exp) interfaceToExpVal(v interface{}) expvar.Var { + switch i := v.(type) { + case string: + newV := new(expvar.String) + newV.Set(i) + return newV + case int64: + newV := new(expvar.Int) + newV.Set(i) + return newV + case int32: + newV := new(expvar.Int) + newV.Set(int64(i)) + return newV + case int16: + newV := new(expvar.Int) + newV.Set(int64(i)) + return newV + case int8: + newV := new(expvar.Int) + newV.Set(int64(i)) + return newV + case int: + newV := new(expvar.Int) + newV.Set(int64(i)) + return newV + case float32: + newV := new(expvar.Float) + newV.Set(float64(i)) + return newV + case float64: + newV := new(expvar.Float) + newV.Set(i) + return newV + case map[string]interface{}: + newV := new(expvar.Map) + for k, v := range i { + newV.Set(k, exp.interfaceToExpVal(v)) + } + return newV + default: + newV := new(expvar.String) + newV.Set(fmt.Sprint(v)) + return newV + } +} + func (exp *exp) syncToExpvar() { exp.registry.Each(func(name string, i interface{}) { switch i := i.(type) { @@ -179,6 +247,8 @@ func (exp *exp) syncToExpvar() { exp.publishTimer(name, i) case metrics.ResettingTimer: exp.publishResettingTimer(name, i) + case metrics.Label: + exp.publishLabel(name, i) default: panic(fmt.Sprintf("unsupported type for '%s': %T", name, i)) } diff --git a/metrics/label.go b/metrics/label.go new file mode 100644 index 0000000000..6c6b02ed7f --- /dev/null +++ b/metrics/label.go @@ -0,0 +1,48 @@ +package metrics + +import "encoding/json" + +// Label hold an map[string]interface{} value that can be set arbitrarily. +type Label interface { + Value() map[string]interface{} + String() string + Mark(map[string]interface{}) +} + +// NewRegisteredLabel constructs and registers a new StandardLabel. +func NewRegisteredLabel(name string, r Registry) Label { + c := NewStandardLabel() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewStandardLabel constructs a new StandardLabel. +func NewStandardLabel() *StandardLabel { + return &StandardLabel{} +} + +// StandardLabel is the standard implementation of a Label. +type StandardLabel struct { + value map[string]interface{} + jsonStr string +} + +// Value returns label values. +func (l *StandardLabel) Value() map[string]interface{} { + return l.value +} + +// Mark records the label. +func (l *StandardLabel) Mark(value map[string]interface{}) { + buf, _ := json.Marshal(value) + l.jsonStr = string(buf) + l.value = value +} + +// String returns label by JSON format. +func (l *StandardLabel) String() string { + return l.jsonStr +} diff --git a/metrics/prometheus/collector.go b/metrics/prometheus/collector.go index 3959cbf5e1..25c7b4f4c4 100644 --- a/metrics/prometheus/collector.go +++ b/metrics/prometheus/collector.go @@ -31,6 +31,7 @@ var ( typeSummaryTpl = "# TYPE %s summary\n" keyValueTpl = "%s %v\n\n" keyQuantileTagValueTpl = "%s {quantile=\"%s\"} %v\n" + keyLabelValueTpl = "%s%s %v\n\n" ) // collector is a collection of byte buffers that aggregate Prometheus reports @@ -98,6 +99,15 @@ func (c *collector) addResettingTimer(name string, m metrics.ResettingTimer) { c.buff.WriteRune('\n') } +func (c *collector) addLabel(name string, m metrics.Label) { + c.writeLabel(mutateKey(name), m.String()) +} + +func (c *collector) writeLabel(name string, value interface{}) { + c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name)) + c.buff.WriteString(fmt.Sprintf(keyLabelValueTpl, name, value, 1)) +} + func (c *collector) writeGaugeCounter(name string, value interface{}) { name = mutateKey(name) c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name)) diff --git a/metrics/prometheus/prometheus.go b/metrics/prometheus/prometheus.go index 9ad5ec7e99..2b94266cbc 100644 --- a/metrics/prometheus/prometheus.go +++ b/metrics/prometheus/prometheus.go @@ -57,6 +57,8 @@ func Handler(reg metrics.Registry) http.Handler { c.addTimer(name, m.Snapshot()) case metrics.ResettingTimer: c.addResettingTimer(name, m.Snapshot()) + case metrics.Label: + c.addLabel(name, m) default: log.Warn("Unknown Prometheus metric type", "type", fmt.Sprintf("%T", i)) } diff --git a/metrics/registry.go b/metrics/registry.go index c5435adf24..8ab519fcfb 100644 --- a/metrics/registry.go +++ b/metrics/registry.go @@ -196,7 +196,7 @@ func (r *StandardRegistry) register(name string, i interface{}) error { return DuplicateMetric(name) } switch i.(type) { - case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer: + case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer, Label: r.metrics[name] = i } return nil