diff --git a/Gopkg.lock b/Gopkg.lock index c1175b82eb..935bdd3efb 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -17,14 +17,6 @@ pruneopts = "" revision = "3a771d992973f24aa725d07868b467d1ddfceafb" -[[projects]] - digest = "1:47fe89a242ccbae03d31b4c665d3d983786acd316c0d7c51bcfa0d019b205004" - name = "github.com/cactus/go-statsd-client" - packages = ["statsd"] - pruneopts = "" - revision = "138b925ccdf617776955904ba7759fce64406cec" - version = "v3.1.1" - [[projects]] digest = "1:87021a8fd708a9c4dd48a441cc2dace8063f2c1f5d67699ba6f1f93b548e4a33" name = "github.com/cloudflare/cfssl" @@ -55,14 +47,6 @@ revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" -[[projects]] - branch = "master" - digest = "1:88b37f144a80737f9e5cd50c887c00c2f3c7211257f884b8b80ce97e61ed1ccb" - name = "github.com/facebookgo/clock" - packages = ["."] - pruneopts = "" - revision = "600d898af40aa09a7a93ecb9265d87b0504b6f03" - [[projects]] digest = "1:eb53021a8aa3f599d29c7102e65026242bdedce998a54837dc67f14b6a97c5fd" name = "github.com/fsnotify/fsnotify" @@ -71,13 +55,37 @@ revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" version = "v1.4.7" +[[projects]] + digest = "1:48e65aaf8ce34ffb3e8d56daa9417826db162afbc2040705db331e9a2e9eebe3" + name = "github.com/go-kit/kit" + packages = [ + "log", + "metrics", + "metrics/internal/lv", + "metrics/internal/ratemap", + "metrics/prometheus", + "metrics/statsd", + "util/conn", + ] + pruneopts = "" + revision = "12210fb6ace19e0496167bb3e667dcd91fa9f69b" + version = "v0.8.0" + +[[projects]] + digest = "1:df89444601379b2e1ee82bf8e6b72af9901cbeed4b469fa380a519c89c339310" + name = "github.com/go-logfmt/logfmt" + packages = ["."] + pruneopts = "" + revision = "07c9b44f60d7ffdfb7d8efe1ad539965737836dc" + version = "v0.4.0" + [[projects]] branch = "master" - digest = "1:85e195bd952faa2e720f5c371d0993af6d515cfcda3894de9caf5c896165cd8c" + digest = "1:9949f4a2c726614c4d38ca692705f9f0a894122406e78cb62dc69ff267705483" name = "github.com/golang/mock" packages = ["gomock"] pruneopts = "" - revision = "b3e60bcdc577185fce3cf625fc96b62857ce5574" + revision = "c20582278a829e4b3259747a3ce0eceb1763ee13" [[projects]] digest = "1:f958a1c137db276e52f0b50efee41a1a389dcdded59a69711f3e872757dab34b" @@ -125,6 +133,22 @@ pruneopts = "" revision = "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8" +[[projects]] + digest = "1:f4e34f94e4873a32542b96bfd884df686b26c458f27ad719569e048abcc2b350" + name = "github.com/hyperledger/fabric-lib-go" + packages = ["healthz"] + pruneopts = "" + revision = "90dc96fb23ab7eb18477e4bfcf9cd8ebdb7209f0" + version = "v1.0.0" + +[[projects]] + branch = "master" + digest = "1:1ed9eeebdf24aadfbca57eb50e6455bd1d2474525e0f0d4454de8c8e9bc7ee9a" + name = "github.com/kr/logfmt" + packages = ["."] + pruneopts = "" + revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" + [[projects]] digest = "1:739b2038a38cebb50e922d18f4b042c042256320fea2db094814aeef8891e0c1" name = "github.com/magiconair/properties" @@ -184,10 +208,7 @@ [[projects]] digest = "1:4142d94383572e74b42352273652c62afec5b23f325222ed09198f46009022d1" name = "github.com/prometheus/client_golang" - packages = [ - "prometheus", - "prometheus/promhttp", - ] + packages = ["prometheus"] pruneopts = "" revision = "c5b7fccd204277076155f10851dad72b76a49317" version = "v0.8.0" @@ -279,18 +300,6 @@ revision = "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c" version = "v1.2.0" -[[projects]] - digest = "1:67e9afe57bd4a951c89b694c39bc0485d7ac94df254316a9b28633bd938bdcf4" - name = "github.com/uber-go/tally" - packages = [ - ".", - "prometheus", - "statsd", - ] - pruneopts = "" - revision = "522328b48efad0c6034dba92bf39228694e9d31f" - version = "v3.3.2" - [[projects]] branch = "master" digest = "1:f8e4d7d2ee6f5f8a2d0c006a57763552dc013d06925f239b8f3c3a7a1f398920" @@ -407,28 +416,27 @@ analyzer-version = 1 input-imports = [ "github.com/Knetic/govaluate", - "github.com/cactus/go-statsd-client/statsd", "github.com/cloudflare/cfssl/api", "github.com/cloudflare/cfssl/csr", "github.com/cloudflare/cfssl/helpers", "github.com/cloudflare/cfssl/log", "github.com/cloudflare/cfssl/signer", + "github.com/go-kit/kit/metrics", + "github.com/go-kit/kit/metrics/prometheus", + "github.com/go-kit/kit/metrics/statsd", "github.com/golang/mock/gomock", "github.com/golang/protobuf/proto", "github.com/golang/protobuf/ptypes", "github.com/golang/protobuf/ptypes/timestamp", + "github.com/hyperledger/fabric-lib-go/healthz", "github.com/miekg/pkcs11", "github.com/mitchellh/mapstructure", "github.com/pkg/errors", "github.com/prometheus/client_golang/prometheus", - "github.com/prometheus/client_golang/prometheus/promhttp", "github.com/spf13/cast", "github.com/spf13/viper", "github.com/stretchr/testify/assert", "github.com/stretchr/testify/require", - "github.com/uber-go/tally", - "github.com/uber-go/tally/prometheus", - "github.com/uber-go/tally/statsd", "golang.org/x/crypto/ocsp", "golang.org/x/crypto/sha3", "golang.org/x/net/context", diff --git a/Gopkg.toml b/Gopkg.toml index 0dc43d2ea3..8c747f519a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -52,8 +52,6 @@ name = "github.com/stretchr/testify" version = "1.2.0" -# tally is used only if performance is enabled -# using the pprof build tag (normal sdk build does not use this library) [[constraint]] - name = "github.com/uber-go/tally" - version = "=3.3.2" + name = "github.com/hyperledger/fabric-lib-go" + version = "1.0.0" \ No newline at end of file diff --git a/internal/github.com/hyperledger/fabric/common/metrics/disabled/provider.go b/internal/github.com/hyperledger/fabric/common/metrics/disabled/provider.go new file mode 100644 index 0000000000..099e37e5fe --- /dev/null +++ b/internal/github.com/hyperledger/fabric/common/metrics/disabled/provider.go @@ -0,0 +1,43 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package disabled + +import ( + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" +) + +type Provider struct{} + +func (p *Provider) NewCounter(o metrics.CounterOpts) metrics.Counter { return &Counter{} } +func (p *Provider) NewGauge(o metrics.GaugeOpts) metrics.Gauge { return &Gauge{} } +func (p *Provider) NewHistogram(o metrics.HistogramOpts) metrics.Histogram { return &Histogram{} } + +type Counter struct{} + +func (c *Counter) Add(delta float64) {} +func (c *Counter) With(labelValues ...string) metrics.Counter { + return c +} + +type Gauge struct{} + +func (g *Gauge) Add(delta float64) {} +func (g *Gauge) Set(delta float64) {} +func (g *Gauge) With(labelValues ...string) metrics.Gauge { + return g +} + +type Histogram struct{} + +func (h *Histogram) Observe(value float64) {} +func (h *Histogram) With(labelValues ...string) metrics.Histogram { + return h +} diff --git a/internal/github.com/hyperledger/fabric/common/metrics/internal/namer/namer.go b/internal/github.com/hyperledger/fabric/common/metrics/internal/namer/namer.go new file mode 100644 index 0000000000..d833071d7f --- /dev/null +++ b/internal/github.com/hyperledger/fabric/common/metrics/internal/namer/namer.go @@ -0,0 +1,148 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package namer + +import ( + "fmt" + "regexp" + "strings" + + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" +) + +type Namer struct { + namespace string + subsystem string + name string + nameFormat string + labelNames map[string]struct{} +} + +func NewCounterNamer(c metrics.CounterOpts) *Namer { + return &Namer{ + namespace: c.Namespace, + subsystem: c.Subsystem, + name: c.Name, + nameFormat: c.StatsdFormat, + labelNames: sliceToSet(c.LabelNames), + } +} + +func NewGaugeNamer(g metrics.GaugeOpts) *Namer { + return &Namer{ + namespace: g.Namespace, + subsystem: g.Subsystem, + name: g.Name, + nameFormat: g.StatsdFormat, + labelNames: sliceToSet(g.LabelNames), + } +} + +func NewHistogramNamer(h metrics.HistogramOpts) *Namer { + return &Namer{ + namespace: h.Namespace, + subsystem: h.Subsystem, + name: h.Name, + nameFormat: h.StatsdFormat, + labelNames: sliceToSet(h.LabelNames), + } +} + +func (n *Namer) validateKey(name string) { + if _, ok := n.labelNames[name]; !ok { + panic("invalid label name: " + name) + } +} + +func (n *Namer) FullyQualifiedName() string { + switch { + case n.namespace != "" && n.subsystem != "": + return strings.Join([]string{n.namespace, n.subsystem, n.name}, ".") + case n.namespace != "": + return strings.Join([]string{n.namespace, n.name}, ".") + case n.subsystem != "": + return strings.Join([]string{n.subsystem, n.name}, ".") + default: + return n.name + } +} + +func (n *Namer) labelsToMap(labelValues []string) map[string]string { + labels := map[string]string{} + for i := 0; i < len(labelValues); i += 2 { + key := labelValues[i] + n.validateKey(key) + if i == len(labelValues)-1 { + labels[key] = "unknown" + } else { + labels[key] = labelValues[i+1] + } + } + return labels +} + +var formatRegexp = regexp.MustCompile(`%{([#?[:alnum:]_]+)}`) +var invalidLabelValueRegexp = regexp.MustCompile(`[.|:\s]`) + +func (n *Namer) Format(labelValues ...string) string { + labels := n.labelsToMap(labelValues) + + cursor := 0 + var segments []string + // iterate over the regex groups and convert to formatters + matches := formatRegexp.FindAllStringSubmatchIndex(n.nameFormat, -1) + for _, m := range matches { + start, end := m[0], m[1] + labelStart, labelEnd := m[2], m[3] + + if start > cursor { + segments = append(segments, n.nameFormat[cursor:start]) + } + + key := n.nameFormat[labelStart:labelEnd] + var value string + switch key { + case "#namespace": + value = n.namespace + case "#subsystem": + value = n.subsystem + case "#name": + value = n.name + case "#fqname": + value = n.FullyQualifiedName() + default: + var ok bool + value, ok = labels[key] + if !ok { + panic(fmt.Sprintf("invalid label in name format: %s", key)) + } + value = invalidLabelValueRegexp.ReplaceAllString(value, "_") + } + segments = append(segments, value) + + cursor = end + } + + // handle any trailing suffix + if cursor != len(n.nameFormat) { + segments = append(segments, n.nameFormat[cursor:]) + } + + return strings.Join(segments, "") +} + +func sliceToSet(set []string) map[string]struct{} { + labelSet := map[string]struct{}{} + for _, s := range set { + labelSet[s] = struct{}{} + } + return labelSet +} diff --git a/internal/github.com/hyperledger/fabric/common/metrics/prometheus/provider.go b/internal/github.com/hyperledger/fabric/common/metrics/prometheus/provider.go new file mode 100644 index 0000000000..9cb167b19c --- /dev/null +++ b/internal/github.com/hyperledger/fabric/common/metrics/prometheus/provider.go @@ -0,0 +1,81 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package prometheus + +import ( + kitmetrics "github.com/go-kit/kit/metrics" + "github.com/go-kit/kit/metrics/prometheus" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" + prom "github.com/prometheus/client_golang/prometheus" +) + +type Provider struct{} + +func (p *Provider) NewCounter(o metrics.CounterOpts) metrics.Counter { + return &Counter{ + Counter: prometheus.NewCounterFrom( + prom.CounterOpts{ + Namespace: o.Namespace, + Subsystem: o.Subsystem, + Name: o.Name, + Help: o.Help, + }, + o.LabelNames, + ), + } +} + +func (p *Provider) NewGauge(o metrics.GaugeOpts) metrics.Gauge { + return &Gauge{ + Gauge: prometheus.NewGaugeFrom( + prom.GaugeOpts{ + Namespace: o.Namespace, + Subsystem: o.Subsystem, + Name: o.Name, + Help: o.Help, + }, + o.LabelNames, + ), + } +} + +func (p *Provider) NewHistogram(o metrics.HistogramOpts) metrics.Histogram { + return &Histogram{ + Histogram: prometheus.NewHistogramFrom( + prom.HistogramOpts{ + Namespace: o.Namespace, + Subsystem: o.Subsystem, + Name: o.Name, + Help: o.Help, + Buckets: o.Buckets, + }, + o.LabelNames, + ), + } +} + +type Counter struct{ kitmetrics.Counter } + +func (c *Counter) With(labelValues ...string) metrics.Counter { + return &Counter{Counter: c.Counter.With(labelValues...)} +} + +type Gauge struct{ kitmetrics.Gauge } + +func (g *Gauge) With(labelValues ...string) metrics.Gauge { + return &Gauge{Gauge: g.Gauge.With(labelValues...)} +} + +type Histogram struct{ kitmetrics.Histogram } + +func (h *Histogram) With(labelValues ...string) metrics.Histogram { + return &Histogram{Histogram: h.Histogram.With(labelValues...)} +} diff --git a/internal/github.com/hyperledger/fabric/common/metrics/statsd/goruntime/collector.go b/internal/github.com/hyperledger/fabric/common/metrics/statsd/goruntime/collector.go new file mode 100644 index 0000000000..726dd1d04a --- /dev/null +++ b/internal/github.com/hyperledger/fabric/common/metrics/statsd/goruntime/collector.go @@ -0,0 +1,134 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package goruntime + +import ( + "runtime" + "time" + + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" +) + +type Collector struct { + CgoCalls metrics.Gauge + GoRoutines metrics.Gauge + ThreadsCreated metrics.Gauge + HeapAlloc metrics.Gauge + TotalAlloc metrics.Gauge + Mallocs metrics.Gauge + Frees metrics.Gauge + HeapSys metrics.Gauge + HeapIdle metrics.Gauge + HeapInuse metrics.Gauge + HeapReleased metrics.Gauge + HeapObjects metrics.Gauge + StackInuse metrics.Gauge + StackSys metrics.Gauge + MSpanInuse metrics.Gauge + MSpanSys metrics.Gauge + MCacheInuse metrics.Gauge + MCacheSys metrics.Gauge + BuckHashSys metrics.Gauge + GCSys metrics.Gauge + OtherSys metrics.Gauge + NextGC metrics.Gauge + LastGC metrics.Gauge + PauseTotalNs metrics.Gauge + PauseNs metrics.Gauge + NumGC metrics.Gauge + NumForcedGC metrics.Gauge +} + +func NewCollector(p metrics.Provider) *Collector { + return &Collector{ + CgoCalls: p.NewGauge(cgoCallsGaugeOpts), + GoRoutines: p.NewGauge(goRoutinesGaugeOpts), + ThreadsCreated: p.NewGauge(threadsCreatedGaugeOpts), + HeapAlloc: p.NewGauge(heapAllocGaugeOpts), + TotalAlloc: p.NewGauge(totalAllocGaugeOpts), + Mallocs: p.NewGauge(mallocsGaugeOpts), + Frees: p.NewGauge(freesGaugeOpts), + HeapSys: p.NewGauge(heapSysGaugeOpts), + HeapIdle: p.NewGauge(heapIdleGaugeOpts), + HeapInuse: p.NewGauge(heapInuseGaugeOpts), + HeapReleased: p.NewGauge(heapReleasedGaugeOpts), + HeapObjects: p.NewGauge(heapObjectsGaugeOpts), + StackInuse: p.NewGauge(stackInuseGaugeOpts), + StackSys: p.NewGauge(stackSysGaugeOpts), + MSpanInuse: p.NewGauge(mSpanInuseGaugeOpts), + MSpanSys: p.NewGauge(mSpanSysGaugeOpts), + MCacheInuse: p.NewGauge(mCacheInuseGaugeOpts), + MCacheSys: p.NewGauge(mCacheSysGaugeOpts), + BuckHashSys: p.NewGauge(buckHashSysGaugeOpts), + GCSys: p.NewGauge(gCSysGaugeOpts), + OtherSys: p.NewGauge(otherSysGaugeOpts), + NextGC: p.NewGauge(nextGCGaugeOpts), + LastGC: p.NewGauge(lastGCGaugeOpts), + PauseTotalNs: p.NewGauge(pauseTotalNsGaugeOpts), + PauseNs: p.NewGauge(pauseNsGaugeOpts), + NumGC: p.NewGauge(numGCGaugeOpts), + NumForcedGC: p.NewGauge(numForcedGCGaugeOpts), + } +} + +func (c *Collector) CollectAndPublish(ticks <-chan time.Time) { + for range ticks { + stats := CollectStats() + c.Publish(stats) + } +} + +func (c *Collector) Publish(stats Stats) { + c.CgoCalls.Set(float64(stats.CgoCalls)) + c.GoRoutines.Set(float64(stats.GoRoutines)) + c.ThreadsCreated.Set(float64(stats.ThreadsCreated)) + c.HeapAlloc.Set(float64(stats.MemStats.HeapAlloc)) + c.TotalAlloc.Set(float64(stats.MemStats.TotalAlloc)) + c.Mallocs.Set(float64(stats.MemStats.Mallocs)) + c.Frees.Set(float64(stats.MemStats.Frees)) + c.HeapSys.Set(float64(stats.MemStats.HeapSys)) + c.HeapIdle.Set(float64(stats.MemStats.HeapIdle)) + c.HeapInuse.Set(float64(stats.MemStats.HeapInuse)) + c.HeapReleased.Set(float64(stats.MemStats.HeapReleased)) + c.HeapObjects.Set(float64(stats.MemStats.HeapObjects)) + c.StackInuse.Set(float64(stats.MemStats.StackInuse)) + c.StackSys.Set(float64(stats.MemStats.StackSys)) + c.MSpanInuse.Set(float64(stats.MemStats.MSpanInuse)) + c.MSpanSys.Set(float64(stats.MemStats.MSpanSys)) + c.MCacheInuse.Set(float64(stats.MemStats.MCacheInuse)) + c.MCacheSys.Set(float64(stats.MemStats.MCacheSys)) + c.BuckHashSys.Set(float64(stats.MemStats.BuckHashSys)) + c.GCSys.Set(float64(stats.MemStats.GCSys)) + c.OtherSys.Set(float64(stats.MemStats.OtherSys)) + c.NextGC.Set(float64(stats.MemStats.NextGC)) + c.LastGC.Set(float64(stats.MemStats.LastGC)) + c.PauseTotalNs.Set(float64(stats.MemStats.PauseTotalNs)) + c.PauseNs.Set(float64(stats.MemStats.PauseNs[(stats.MemStats.NumGC+255)%256])) + c.NumGC.Set(float64(stats.MemStats.NumGC)) + c.NumForcedGC.Set(float64(stats.MemStats.NumForcedGC)) +} + +type Stats struct { + CgoCalls int64 + GoRoutines int + ThreadsCreated int + MemStats runtime.MemStats +} + +func CollectStats() Stats { + stats := Stats{ + CgoCalls: runtime.NumCgoCall(), + GoRoutines: runtime.NumGoroutine(), + } + stats.ThreadsCreated, _ = runtime.ThreadCreateProfile(nil) + runtime.ReadMemStats(&stats.MemStats) + return stats +} diff --git a/internal/github.com/hyperledger/fabric/common/metrics/statsd/goruntime/metrics.go b/internal/github.com/hyperledger/fabric/common/metrics/statsd/goruntime/metrics.go new file mode 100644 index 0000000000..b37c8404f8 --- /dev/null +++ b/internal/github.com/hyperledger/fabric/common/metrics/statsd/goruntime/metrics.go @@ -0,0 +1,47 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package goruntime + +import ( + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" +) + +//gendoc:ignore + +var ( + cgoCallsGaugeOpts = metrics.GaugeOpts{Namespace: "go", Name: "cgo_calls"} + goRoutinesGaugeOpts = metrics.GaugeOpts{Namespace: "go", Name: "goroutine_count"} + threadsCreatedGaugeOpts = metrics.GaugeOpts{Namespace: "go", Name: "threads_created"} + heapAllocGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_alloc_bytes"} + totalAllocGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_total_alloc_bytes"} + mallocsGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_malloc_count"} + freesGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_free_count"} + heapSysGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_sys_bytes"} + heapIdleGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_idle_bytes"} + heapInuseGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_inuse_bytes"} + heapReleasedGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_released_bytes"} + heapObjectsGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "heap_objects"} + stackInuseGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "stack_inuse_bytes"} + stackSysGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "stack_sys_bytes"} + mSpanInuseGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "mspan_inuse_bytes"} + mSpanSysGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "mspan_sys_bytes"} + mCacheInuseGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "mcache_inuse_bytes"} + mCacheSysGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "mcache_sys_bytes"} + buckHashSysGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "buckethash_sys_bytes"} + gCSysGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "gc_sys_bytes"} + otherSysGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "other_sys_bytes"} + nextGCGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "gc_next_bytes"} + lastGCGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "gc_last_epoch_nanotime"} + pauseTotalNsGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "gc_pause_total_ns"} + pauseNsGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "gc_pause_last_ns"} + numGCGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "gc_completed_count"} + numForcedGCGaugeOpts = metrics.GaugeOpts{Namespace: "go", Subsystem: "mem", Name: "gc_forced_count"} +) diff --git a/internal/github.com/hyperledger/fabric/common/metrics/statsd/provider.go b/internal/github.com/hyperledger/fabric/common/metrics/statsd/provider.go new file mode 100644 index 0000000000..ea48b09beb --- /dev/null +++ b/internal/github.com/hyperledger/fabric/common/metrics/statsd/provider.go @@ -0,0 +1,132 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package statsd + +import ( + "github.com/go-kit/kit/metrics/statsd" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics/internal/namer" +) + +const defaultFormat = "%{#fqname}" + +type Provider struct { + Statsd *statsd.Statsd +} + +func (p *Provider) NewCounter(o metrics.CounterOpts) metrics.Counter { + if o.StatsdFormat == "" { + o.StatsdFormat = defaultFormat + } + counter := &Counter{ + statsdProvider: p.Statsd, + namer: namer.NewCounterNamer(o), + } + + if len(o.LabelNames) == 0 { + counter.Counter = p.Statsd.NewCounter(counter.namer.Format(), 1) + } + + return counter +} + +func (p *Provider) NewGauge(o metrics.GaugeOpts) metrics.Gauge { + if o.StatsdFormat == "" { + o.StatsdFormat = defaultFormat + } + gauge := &Gauge{ + statsdProvider: p.Statsd, + namer: namer.NewGaugeNamer(o), + } + + if len(o.LabelNames) == 0 { + gauge.Gauge = p.Statsd.NewGauge(gauge.namer.Format()) + } + + return gauge +} + +func (p *Provider) NewHistogram(o metrics.HistogramOpts) metrics.Histogram { + if o.StatsdFormat == "" { + o.StatsdFormat = defaultFormat + } + histogram := &Histogram{ + statsdProvider: p.Statsd, + namer: namer.NewHistogramNamer(o), + } + + if len(o.LabelNames) == 0 { + histogram.Timing = p.Statsd.NewTiming(histogram.namer.Format(), 1.0) + } + + return histogram +} + +type Counter struct { + Counter *statsd.Counter + namer *namer.Namer + statsdProvider *statsd.Statsd +} + +func (c *Counter) Add(delta float64) { + if c.Counter == nil { + panic("label values must be provided by calling With") + } + c.Counter.Add(delta) +} + +func (c *Counter) With(labelValues ...string) metrics.Counter { + name := c.namer.Format(labelValues...) + return &Counter{Counter: c.statsdProvider.NewCounter(name, 1)} +} + +type Gauge struct { + Gauge *statsd.Gauge + namer *namer.Namer + statsdProvider *statsd.Statsd +} + +func (g *Gauge) Add(delta float64) { + if g.Gauge == nil { + panic("label values must be provided by calling With") + } + g.Gauge.Add(delta) +} + +func (g *Gauge) Set(value float64) { + if g.Gauge == nil { + panic("label values must be provided by calling With") + } + g.Gauge.Set(value) +} + +func (g *Gauge) With(labelValues ...string) metrics.Gauge { + name := g.namer.Format(labelValues...) + return &Gauge{Gauge: g.statsdProvider.NewGauge(name)} +} + +type Histogram struct { + Timing *statsd.Timing + namer *namer.Namer + statsdProvider *statsd.Statsd +} + +func (h *Histogram) With(labelValues ...string) metrics.Histogram { + name := h.namer.Format(labelValues...) + return &Histogram{Timing: h.statsdProvider.NewTiming(name, 1)} +} + +func (h *Histogram) Observe(value float64) { + if h.Timing == nil { + panic("label values must be provided by calling With") + } + h.Timing.Observe(value) +} diff --git a/internal/github.com/hyperledger/fabric/common/util/utils.go b/internal/github.com/hyperledger/fabric/common/util/utils.go index 8bf940b276..617775be23 100644 --- a/internal/github.com/hyperledger/fabric/common/util/utils.go +++ b/internal/github.com/hyperledger/fabric/common/util/utils.go @@ -21,6 +21,10 @@ Please review third_party pinning scripts and patches for more details. package util import ( + "crypto/rand" + "fmt" + "io" + "math/big" "time" "github.com/golang/protobuf/ptypes/timestamp" @@ -28,6 +32,36 @@ import ( const defaultAlg = "sha256" +// GenerateBytesUUID returns a UUID based on RFC 4122 returning the generated bytes +func GenerateBytesUUID() []byte { + uuid := make([]byte, 16) + _, err := io.ReadFull(rand.Reader, uuid) + if err != nil { + panic(fmt.Sprintf("Error generating UUID: %s", err)) + } + + // variant bits; see section 4.1.1 + uuid[8] = uuid[8]&^0xc0 | 0x80 + + // version 4 (pseudo-random); see section 4.1.3 + uuid[6] = uuid[6]&^0xf0 | 0x40 + + return uuid +} + +// GenerateIntUUID returns a UUID based on RFC 4122 returning a big.Int +func GenerateIntUUID() *big.Int { + uuid := GenerateBytesUUID() + z := big.NewInt(0) + return z.SetBytes(uuid) +} + +// GenerateUUID returns a UUID based on RFC 4122 +func GenerateUUID() string { + uuid := GenerateBytesUUID() + return idBytesToStr(uuid) +} + // CreateUtcTimestamp returns a google/protobuf/Timestamp in UTC func CreateUtcTimestamp() *timestamp.Timestamp { now := time.Now().UTC() @@ -36,6 +70,10 @@ func CreateUtcTimestamp() *timestamp.Timestamp { return &(timestamp.Timestamp{Seconds: secs, Nanos: nanos}) } +func idBytesToStr(id []byte) string { + return fmt.Sprintf("%x-%x-%x-%x-%x", id[0:4], id[4:6], id[6:8], id[8:10], id[10:]) +} + const testchainid = "testchainid" const testorgid = "**TEST_ORGID**" diff --git a/internal/github.com/hyperledger/fabric/core/comm/config.go b/internal/github.com/hyperledger/fabric/core/comm/config.go new file mode 100644 index 0000000000..b0b6ffd143 --- /dev/null +++ b/internal/github.com/hyperledger/fabric/core/comm/config.go @@ -0,0 +1,176 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package comm + +import ( + "crypto/tls" + "crypto/x509" + "time" + + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" + flogging "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge" + "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" +) + +// Configuration defaults +var ( + // Max send and receive bytes for grpc clients and servers + MaxRecvMsgSize = 100 * 1024 * 1024 + MaxSendMsgSize = 100 * 1024 * 1024 + // Default peer keepalive options + DefaultKeepaliveOptions = &KeepaliveOptions{ + ClientInterval: time.Duration(1) * time.Minute, // 1 min + ClientTimeout: time.Duration(20) * time.Second, // 20 sec - gRPC default + ServerInterval: time.Duration(2) * time.Hour, // 2 hours - gRPC default + ServerTimeout: time.Duration(20) * time.Second, // 20 sec - gRPC default + ServerMinInterval: time.Duration(1) * time.Minute, // match ClientInterval + } + // strong TLS cipher suites + DefaultTLSCipherSuites = []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + } + // default connection timeout + DefaultConnectionTimeout = 5 * time.Second +) + +// ServerConfig defines the parameters for configuring a GRPCServer instance +type ServerConfig struct { + // ConnectionTimeout specifies the timeout for connection establishment + // for all new connections + ConnectionTimeout time.Duration + // SecOpts defines the security parameters + SecOpts *SecureOptions + // KaOpts defines the keepalive parameters + KaOpts *KeepaliveOptions + // StreamInterceptors specifies a list of interceptors to apply to + // streaming RPCs. They are executed in order. + StreamInterceptors []grpc.StreamServerInterceptor + // UnaryInterceptors specifies a list of interceptors to apply to unary + // RPCs. They are executed in order. + UnaryInterceptors []grpc.UnaryServerInterceptor + // Logger specifies the logger the server will use + Logger *flogging.Logger + // Metrics Provider + MetricsProvider metrics.Provider + // HealthCheckEnabled enables the gRPC Health Checking Protocol for the server + HealthCheckEnabled bool +} + +// ClientConfig defines the parameters for configuring a GRPCClient instance +type ClientConfig struct { + // SecOpts defines the security parameters + SecOpts *SecureOptions + // KaOpts defines the keepalive parameters + KaOpts *KeepaliveOptions + // Timeout specifies how long the client will block when attempting to + // establish a connection + Timeout time.Duration + // AsyncConnect makes connection creation non blocking + AsyncConnect bool +} + +// SecureOptions defines the security parameters (e.g. TLS) for a +// GRPCServer or GRPCClient instance +type SecureOptions struct { + // VerifyCertificate, if not nil, is called after normal + // certificate verification by either a TLS client or server. + // If it returns a non-nil error, the handshake is aborted and that error results. + VerifyCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error + // PEM-encoded X509 public key to be used for TLS communication + Certificate []byte + // PEM-encoded private key to be used for TLS communication + Key []byte + // Set of PEM-encoded X509 certificate authorities used by clients to + // verify server certificates + ServerRootCAs [][]byte + // Set of PEM-encoded X509 certificate authorities used by servers to + // verify client certificates + ClientRootCAs [][]byte + // Whether or not to use TLS for communication + UseTLS bool + // Whether or not TLS client must present certificates for authentication + RequireClientCert bool + // CipherSuites is a list of supported cipher suites for TLS + CipherSuites []uint16 +} + +// KeepaliveOptions is used to set the gRPC keepalive settings for both +// clients and servers +type KeepaliveOptions struct { + // ClientInterval is the duration after which if the client does not see + // any activity from the server it pings the server to see if it is alive + ClientInterval time.Duration + // ClientTimeout is the duration the client waits for a response + // from the server after sending a ping before closing the connection + ClientTimeout time.Duration + // ServerInterval is the duration after which if the server does not see + // any activity from the client it pings the client to see if it is alive + ServerInterval time.Duration + // ServerTimeout is the duration the server waits for a response + // from the client after sending a ping before closing the connection + ServerTimeout time.Duration + // ServerMinInterval is the minimum permitted time between client pings. + // If clients send pings more frequently, the server will disconnect them + ServerMinInterval time.Duration +} + +type Metrics struct { + // OpenConnCounter keeps track of number of open connections + OpenConnCounter metrics.Counter + // ClosedConnCounter keeps track of number connections closed + ClosedConnCounter metrics.Counter +} + +// ServerKeepaliveOptions returns gRPC keepalive options for server. If +// opts is nil, the default keepalive options are returned +func ServerKeepaliveOptions(ka *KeepaliveOptions) []grpc.ServerOption { + // use default keepalive options if nil + if ka == nil { + ka = DefaultKeepaliveOptions + } + var serverOpts []grpc.ServerOption + kap := keepalive.ServerParameters{ + Time: ka.ServerInterval, + Timeout: ka.ServerTimeout, + } + serverOpts = append(serverOpts, grpc.KeepaliveParams(kap)) + kep := keepalive.EnforcementPolicy{ + MinTime: ka.ServerMinInterval, + // allow keepalive w/o rpc + PermitWithoutStream: true, + } + serverOpts = append(serverOpts, grpc.KeepaliveEnforcementPolicy(kep)) + return serverOpts +} + +// ClientKeepaliveOptions returns gRPC keepalive options for clients. If +// opts is nil, the default keepalive options are returned +func ClientKeepaliveOptions(ka *KeepaliveOptions) []grpc.DialOption { + // use default keepalive options if nil + if ka == nil { + ka = DefaultKeepaliveOptions + } + + var dialOpts []grpc.DialOption + kap := keepalive.ClientParameters{ + Time: ka.ClientInterval, + Timeout: ka.ClientTimeout, + PermitWithoutStream: true, + } + dialOpts = append(dialOpts, grpc.WithKeepaliveParams(kap)) + return dialOpts +} diff --git a/internal/github.com/hyperledger/fabric/core/middleware/chain.go b/internal/github.com/hyperledger/fabric/core/middleware/chain.go new file mode 100644 index 0000000000..c14acf5a27 --- /dev/null +++ b/internal/github.com/hyperledger/fabric/core/middleware/chain.go @@ -0,0 +1,42 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package middleware + +import ( + "net/http" +) + +type Middleware func(http.Handler) http.Handler + +// A Chain is a middleware chain use for http request processing. +type Chain struct { + mw []Middleware +} + +// NewChain creates a new Middleware chain. The chain will call the Middleware +// in the order provided. +func NewChain(middlewares ...Middleware) Chain { + return Chain{ + mw: append([]Middleware{}, middlewares...), + } +} + +// Handler returns an http.Handler for this chain. +func (c Chain) Handler(h http.Handler) http.Handler { + if h == nil { + h = http.DefaultServeMux + } + + for i := len(c.mw) - 1; i >= 0; i-- { + h = c.mw[i](h) + } + return h +} diff --git a/internal/github.com/hyperledger/fabric/core/middleware/request_id.go b/internal/github.com/hyperledger/fabric/core/middleware/request_id.go new file mode 100644 index 0000000000..45e8183735 --- /dev/null +++ b/internal/github.com/hyperledger/fabric/core/middleware/request_id.go @@ -0,0 +1,55 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package middleware + +import ( + "context" + "net/http" +) + +var requestIDKey = requestIDKeyType{} + +type requestIDKeyType struct{} + +func RequestID(ctx context.Context) string { + if reqID, ok := ctx.Value(requestIDKey).(string); ok { + return reqID + } + return "unknown" +} + +type GenerateIDFunc func() string + +type requestID struct { + generateID GenerateIDFunc + next http.Handler +} + +func WithRequestID(generator GenerateIDFunc) Middleware { + return func(next http.Handler) http.Handler { + return &requestID{next: next, generateID: generator} + } +} + +func (r *requestID) ServeHTTP(w http.ResponseWriter, req *http.Request) { + reqID := req.Header.Get("X-Request-Id") + if reqID == "" { + reqID = r.generateID() + req.Header.Set("X-Request-Id", reqID) + } + + ctx := context.WithValue(req.Context(), requestIDKey, reqID) + req = req.WithContext(ctx) + + w.Header().Add("X-Request-Id", reqID) + + r.next.ServeHTTP(w, req) +} diff --git a/internal/github.com/hyperledger/fabric/core/middleware/require_cert.go b/internal/github.com/hyperledger/fabric/core/middleware/require_cert.go new file mode 100644 index 0000000000..c94a2da7fb --- /dev/null +++ b/internal/github.com/hyperledger/fabric/core/middleware/require_cert.go @@ -0,0 +1,40 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package middleware + +import ( + "net/http" +) + +type requireCert struct { + next http.Handler +} + +// RequireCert is used to ensure that a verified TLS client certificate was +// used for authentication. +func RequireCert() Middleware { + return func(next http.Handler) http.Handler { + return &requireCert{next: next} + } +} + +func (r *requireCert) ServeHTTP(w http.ResponseWriter, req *http.Request) { + switch { + case req.TLS == nil: + fallthrough + case len(req.TLS.VerifiedChains) == 0: + fallthrough + case len(req.TLS.VerifiedChains[0]) == 0: + w.WriteHeader(http.StatusUnauthorized) + default: + r.next.ServeHTTP(w, req) + } +} diff --git a/internal/github.com/hyperledger/fabric/core/operations/metrics.go b/internal/github.com/hyperledger/fabric/core/operations/metrics.go new file mode 100644 index 0000000000..df4f2e70a7 --- /dev/null +++ b/internal/github.com/hyperledger/fabric/core/operations/metrics.go @@ -0,0 +1,45 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package operations + +import ( + "sync" + + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics/prometheus" +) + +var ( + fabricVersion = metrics.GaugeOpts{ + Name: "fabric_version", + Help: "The active version of Fabric.", + LabelNames: []string{"version"}, + StatsdFormat: "%{#fqname}.%{version}", + } + + gaugeLock sync.Mutex + promVersionGauge metrics.Gauge +) + +func versionGauge(provider metrics.Provider) metrics.Gauge { + switch provider.(type) { + case *prometheus.Provider: + gaugeLock.Lock() + defer gaugeLock.Unlock() + if promVersionGauge == nil { + promVersionGauge = provider.NewGauge(fabricVersion) + } + return promVersionGauge + + default: + return provider.NewGauge(fabricVersion) + } +} diff --git a/internal/github.com/hyperledger/fabric/core/operations/system.go b/internal/github.com/hyperledger/fabric/core/operations/system.go new file mode 100644 index 0000000000..4d0328377f --- /dev/null +++ b/internal/github.com/hyperledger/fabric/core/operations/system.go @@ -0,0 +1,255 @@ +/* +Copyright IBM Corp All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package operations + +import ( + "context" + "crypto/tls" + "net" + "net/http" + "os" + "strings" + "time" + + kitstatsd "github.com/go-kit/kit/metrics/statsd" + "github.com/hyperledger/fabric-lib-go/healthz" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics/disabled" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics/prometheus" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics/statsd" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics/statsd/goruntime" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/core/middleware" + flogging "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge/httpadmin" + prom "github.com/prometheus/client_golang/prometheus" +) + +//go:generate counterfeiter -o fakes/logger.go -fake-name Logger . Logger + +type Logger interface { + Warn(args ...interface{}) + Warnf(template string, args ...interface{}) +} + +type Statsd struct { + Network string + Address string + WriteInterval time.Duration + Prefix string +} + +type MetricsOptions struct { + Provider string + Statsd *Statsd +} + +type Options struct { + Logger Logger + ListenAddress string + Metrics MetricsOptions + TLS TLS + Version string +} + +type System struct { + metrics.Provider + + logger Logger + healthHandler *healthz.HealthHandler + options Options + statsd *kitstatsd.Statsd + collectorTicker *time.Ticker + sendTicker *time.Ticker + httpServer *http.Server + mux *http.ServeMux + addr string + versionGauge metrics.Gauge +} + +func NewSystem(o Options) *System { + logger := o.Logger + if logger == nil { + logger = flogging.MustGetLogger("operations.runner") + } + + system := &System{ + logger: logger, + options: o, + } + + system.initializeServer() + system.initializeHealthCheckHandler() + system.initializeLoggingHandler() + system.initializeMetricsProvider() + + return system +} + +func (s *System) Run(signals <-chan os.Signal, ready chan<- struct{}) error { + err := s.Start() + if err != nil { + return err + } + + close(ready) + + select { + case <-signals: + return s.Stop() + } +} + +func (s *System) Start() error { + err := s.startMetricsTickers() + if err != nil { + return err + } + + s.versionGauge.With("version", s.options.Version).Set(1) + + listener, err := s.listen() + if err != nil { + return err + } + s.addr = listener.Addr().String() + + go s.httpServer.Serve(listener) + + return nil +} + +func (s *System) Stop() error { + if s.collectorTicker != nil { + s.collectorTicker.Stop() + s.collectorTicker = nil + } + if s.sendTicker != nil { + s.sendTicker.Stop() + s.sendTicker = nil + } + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + return s.httpServer.Shutdown(ctx) +} + +func (s *System) RegisterChecker(component string, checker healthz.HealthChecker) error { + return s.healthHandler.RegisterChecker(component, checker) +} + +func (s *System) initializeServer() { + s.mux = http.NewServeMux() + s.httpServer = &http.Server{ + Addr: s.options.ListenAddress, + Handler: s.mux, + ReadTimeout: 10 * time.Second, + WriteTimeout: 2 * time.Minute, + } +} + +func (s *System) handlerChain(h http.Handler, secure bool) http.Handler { + if secure { + return middleware.NewChain(middleware.RequireCert(), middleware.WithRequestID(util.GenerateUUID)).Handler(h) + } + return middleware.NewChain(middleware.WithRequestID(util.GenerateUUID)).Handler(h) +} + +func (s *System) initializeMetricsProvider() error { + m := s.options.Metrics + providerType := m.Provider + switch providerType { + case "statsd": + prefix := m.Statsd.Prefix + if prefix != "" && !strings.HasSuffix(prefix, ".") { + prefix = prefix + "." + } + + ks := kitstatsd.New(prefix, s) + s.Provider = &statsd.Provider{Statsd: ks} + s.statsd = ks + s.versionGauge = versionGauge(s.Provider) + return nil + + case "prometheus": + s.Provider = &prometheus.Provider{} + s.versionGauge = versionGauge(s.Provider) + s.mux.Handle("/metrics", s.handlerChain(prom.Handler(), s.options.TLS.Enabled)) + return nil + + default: + if providerType != "disabled" { + s.logger.Warnf("Unknown provider type: %s; metrics disabled", providerType) + } + + s.Provider = &disabled.Provider{} + s.versionGauge = versionGauge(s.Provider) + return nil + } +} + +func (s *System) initializeLoggingHandler() { + s.mux.Handle("/logspec", s.handlerChain(httpadmin.NewSpecHandler(), s.options.TLS.Enabled)) +} + +func (s *System) initializeHealthCheckHandler() { + s.healthHandler = healthz.NewHealthHandler() + s.mux.Handle("/healthz", s.handlerChain(s.healthHandler, false)) +} + +func (s *System) startMetricsTickers() error { + m := s.options.Metrics + if s.statsd != nil { + network := m.Statsd.Network + address := m.Statsd.Address + c, err := net.Dial(network, address) + if err != nil { + return err + } + c.Close() + + opts := s.options.Metrics.Statsd + writeInterval := opts.WriteInterval + + s.collectorTicker = time.NewTicker(writeInterval / 2) + goCollector := goruntime.NewCollector(s.Provider) + go goCollector.CollectAndPublish(s.collectorTicker.C) + + s.sendTicker = time.NewTicker(writeInterval) + go s.statsd.SendLoop(s.sendTicker.C, network, address) + } + + return nil +} + +func (s *System) listen() (net.Listener, error) { + listener, err := net.Listen("tcp", s.options.ListenAddress) + if err != nil { + return nil, err + } + tlsConfig, err := s.options.TLS.Config() + if err != nil { + return nil, err + } + if tlsConfig != nil { + listener = tls.NewListener(listener, tlsConfig) + } + return listener, nil +} + +func (s *System) Addr() string { + return s.addr +} + +func (s *System) Log(keyvals ...interface{}) error { + s.logger.Warn(keyvals...) + return nil +} diff --git a/internal/github.com/hyperledger/fabric/core/operations/tls.go b/internal/github.com/hyperledger/fabric/core/operations/tls.go new file mode 100644 index 0000000000..23586061ae --- /dev/null +++ b/internal/github.com/hyperledger/fabric/core/operations/tls.go @@ -0,0 +1,58 @@ +/* +Copyright IBM Corp All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package operations + +import ( + "crypto/tls" + "crypto/x509" + "io/ioutil" + + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/core/comm" +) + +type TLS struct { + Enabled bool + CertFile string + KeyFile string + ClientCertRequired bool + ClientCACertFiles []string +} + +func (t TLS) Config() (*tls.Config, error) { + var tlsConfig *tls.Config + + if t.Enabled { + cert, err := tls.LoadX509KeyPair(t.CertFile, t.KeyFile) + if err != nil { + return nil, err + } + caCertPool := x509.NewCertPool() + for _, caPath := range t.ClientCACertFiles { + caPem, err := ioutil.ReadFile(caPath) + if err != nil { + return nil, err + } + caCertPool.AppendCertsFromPEM(caPem) + } + tlsConfig = &tls.Config{ + Certificates: []tls.Certificate{cert}, + CipherSuites: comm.DefaultTLSCipherSuites, + ClientCAs: caCertPool, + } + if t.ClientCertRequired { + tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert + } else { + tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven + } + } + + return tlsConfig, nil +} diff --git a/internal/github.com/hyperledger/fabric/sdkpatch/logbridge/httpadmin/spec.go b/internal/github.com/hyperledger/fabric/sdkpatch/logbridge/httpadmin/spec.go new file mode 100644 index 0000000000..42ac0ef077 --- /dev/null +++ b/internal/github.com/hyperledger/fabric/sdkpatch/logbridge/httpadmin/spec.go @@ -0,0 +1,85 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ +/* +Notice: This file has been modified for Hyperledger Fabric SDK Go usage. +Please review third_party pinning scripts and patches for more details. +*/ + +package httpadmin + +import ( + "encoding/json" + "fmt" + "net/http" + + flogging "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge" +) + +//go:generate counterfeiter -o fakes/logging.go -fake-name Logging . Logging + +type Logging interface { + ActivateSpec(spec string) error + Spec() string +} + +type LogSpec struct { + Spec string `json:"spec,omitempty"` +} + +type ErrorResponse struct { + Error string `json:"error"` +} + +func NewSpecHandler() *SpecHandler { + return &SpecHandler{ + Logger: flogging.MustGetLogger("flogging.httpadmin"), + } +} + +type SpecHandler struct { + Logging Logging + Logger *flogging.Logger +} + +func (h *SpecHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { + switch req.Method { + case http.MethodPut: + var logSpec LogSpec + decoder := json.NewDecoder(req.Body) + if err := decoder.Decode(&logSpec); err != nil { + h.sendResponse(resp, http.StatusBadRequest, err) + return + } + req.Body.Close() + + if err := h.Logging.ActivateSpec(logSpec.Spec); err != nil { + h.sendResponse(resp, http.StatusBadRequest, err) + return + } + resp.WriteHeader(http.StatusNoContent) + + case http.MethodGet: + h.sendResponse(resp, http.StatusOK, &LogSpec{Spec: h.Logging.Spec()}) + + default: + err := fmt.Errorf("invalid request method: %s", req.Method) + h.sendResponse(resp, http.StatusBadRequest, err) + } +} + +func (h *SpecHandler) sendResponse(resp http.ResponseWriter, code int, payload interface{}) { + encoder := json.NewEncoder(resp) + if err, ok := payload.(error); ok { + payload = &ErrorResponse{Error: err.Error()} + } + + resp.WriteHeader(code) + + resp.Header().Set("Content-Type", "application/json") + if err := encoder.Encode(payload); err != nil { + h.Logger.Errorf("[error] failed to encode payload", err) + } +} diff --git a/pkg/client/channel/chclient.go b/pkg/client/channel/chclient.go index 8c4e2eb713..1098f1f008 100644 --- a/pkg/client/channel/chclient.go +++ b/pkg/client/channel/chclient.go @@ -28,6 +28,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" contextImpl "github.com/hyperledger/fabric-sdk-go/pkg/context" + "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" "github.com/pkg/errors" ) @@ -41,7 +42,7 @@ type Client struct { membership fab.ChannelMembership eventService fab.EventService greylist *greylist.Filter - clientTally // nolint + metrics *metrics.ClientMetrics } // ClientOption describes a functional parameter for the New constructor diff --git a/pkg/client/channel/chclient_test.go b/pkg/client/channel/chclient_test.go index 3ea37b3dcb..96515ab2c5 100644 --- a/pkg/client/channel/chclient_test.go +++ b/pkg/client/channel/chclient_test.go @@ -72,7 +72,6 @@ func TestTxProposalResponseFilter(t *testing.T) { } func TestQuery(t *testing.T) { - chClient := setupChannelClient(nil, t) _, err := chClient.Query(Request{}) @@ -385,7 +384,6 @@ func TestTransactionValidationError(t *testing.T) { } func TestTransactionTimeout(t *testing.T) { - mockEventService := fcmocks.NewMockEventService() mockEventService.Timeout = true testPeer1 := fcmocks.NewMockPeer("Peer1", "http://peer1.com") @@ -468,7 +466,6 @@ func TestMultiErrorPropogation(t *testing.T) { } func TestDiscoveryGreylist(t *testing.T) { - testPeer1 := fcmocks.NewMockPeer("Peer1", "http://peer1.com") testPeer1.Error = status.New(status.EndorserClientStatus, status.ConnectionFailed.ToInt32(), "test", []interface{}{testPeer1.URL()}) diff --git a/pkg/client/channel/chclientrun.go b/pkg/client/channel/chclientrun.go index 863412c5a5..eac65490c7 100644 --- a/pkg/client/channel/chclientrun.go +++ b/pkg/client/channel/chclientrun.go @@ -1,5 +1,3 @@ -// +build !pprof - /* Copyright SecureKey Technologies Inc. All Rights Reserved. @@ -9,28 +7,18 @@ SPDX-License-Identifier: Apache-2.0 package channel import ( - "github.com/hyperledger/fabric-sdk-go/pkg/client/channel/invoke" "github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/greylist" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" ) -type clientTally interface{} // nolint - func newClient(channelContext context.Channel, membership fab.ChannelMembership, eventService fab.EventService, greylistProvider *greylist.Filter) Client { channelClient := Client{ membership: membership, eventService: eventService, greylist: greylistProvider, context: channelContext, + metrics: channelContext.GetMetrics(), } return channelClient } - -func callQuery(cc *Client, request Request, options ...RequestOption) (Response, error) { - return cc.InvokeHandler(invoke.NewQueryHandler(), request, options...) -} - -func callExecute(cc *Client, request Request, options ...RequestOption) (Response, error) { - return cc.InvokeHandler(invoke.NewExecuteHandler(), request, options...) -} diff --git a/pkg/client/channel/chclientrun_perf.go b/pkg/client/channel/chclientrun_perf.go new file mode 100644 index 0000000000..5146a69bcd --- /dev/null +++ b/pkg/client/channel/chclientrun_perf.go @@ -0,0 +1,72 @@ +// +build pprof + +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package channel + +import ( + "fmt" + "time" + + "github.com/hyperledger/fabric-sdk-go/pkg/client/channel/invoke" + "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/status" +) + +func callQuery(cc *Client, request Request, options ...RequestOption) (Response, error) { + meterLabels := []string{ + "chaincode", request.ChaincodeID, + "Fcn", request.Fcn, + } + cc.metrics.QueriesReceived.With(meterLabels...).Add(1) + startTime := time.Now() + r, err := cc.InvokeHandler(invoke.NewQueryHandler(), request, options...) + if err != nil { + if s, ok := err.(*status.Status); ok { + if s.Code == status.Timeout.ToInt32() { + meterLabels = append(meterLabels, "fail", "timeout") + cc.metrics.QueryTimeouts.With(meterLabels...).Add(1) + return r, err + } + meterLabels = append(meterLabels, "fail", fmt.Sprintf("Error - Group:%s - Code:%d", s.Group.String(), s.Code)) + cc.metrics.QueriesFailed.With(meterLabels...).Add(1) + return r, err + } + meterLabels = append(meterLabels, "fail", fmt.Sprintf("Error - Generic: %s", err)) + cc.metrics.QueriesFailed.With(meterLabels...).Add(1) + return r, err + } + cc.metrics.QueryDuration.With(meterLabels...).Observe(time.Since(startTime).Seconds()) + return r, err +} + +func callExecute(cc *Client, request Request, options ...RequestOption) (Response, error) { + meterLabels := []string{ + "chaincode", request.ChaincodeID, + "Fcn", request.Fcn, + } + cc.metrics.ExecutionsReceived.With(meterLabels...).Add(1) + startTime := time.Now() + r, err := cc.InvokeHandler(invoke.NewExecuteHandler(), request, options...) + if err != nil { + if s, ok := err.(*status.Status); ok { + if s.Code == status.Timeout.ToInt32() { + meterLabels = append(meterLabels, "fail", "timeout") + cc.metrics.ExecutionTimeouts.With(meterLabels...).Add(1) + return r, err + } + meterLabels = append(meterLabels, "fail", fmt.Sprintf("Error - Group:%s - Code:%d", s.Group.String(), s.Code)) + cc.metrics.ExecutionsFailed.With(meterLabels...).Add(1) + return r, err + } + meterLabels = append(meterLabels, "fail", fmt.Sprintf("Error - Generic: %s", err)) + cc.metrics.ExecutionsFailed.With(meterLabels...).Add(1) + return r, err + } + + cc.metrics.ExecutionDuration.With(meterLabels...).Observe(time.Since(startTime).Seconds()) + return r, err +} diff --git a/pkg/client/channel/chclientrun_std.go b/pkg/client/channel/chclientrun_std.go new file mode 100644 index 0000000000..3f2a459a44 --- /dev/null +++ b/pkg/client/channel/chclientrun_std.go @@ -0,0 +1,21 @@ +// +build !pprof + +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package channel + +import ( + "github.com/hyperledger/fabric-sdk-go/pkg/client/channel/invoke" +) + +func callQuery(cc *Client, request Request, options ...RequestOption) (Response, error) { + return cc.InvokeHandler(invoke.NewQueryHandler(), request, options...) +} + +func callExecute(cc *Client, request Request, options ...RequestOption) (Response, error) { + return cc.InvokeHandler(invoke.NewExecuteHandler(), request, options...) +} diff --git a/pkg/client/channel/clientrun_perf.go b/pkg/client/channel/clientrun_perf.go deleted file mode 100644 index f29458ddfd..0000000000 --- a/pkg/client/channel/clientrun_perf.go +++ /dev/null @@ -1,82 +0,0 @@ -// +build pprof - -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package channel - -import ( - // TODO update metrics package with Fabric's copy, once officially released - // TODO and pinned into Go SDK with the below commented out import statement - //"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" - "github.com/hyperledger/fabric-sdk-go/pkg/client/channel/invoke" - "github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/greylist" - "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" - "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" - - // TODO remove below metrics declaration once Fabric's copy is ready to be used - "github.com/hyperledger/fabric-sdk-go/test/performance/metrics" - "github.com/uber-go/tally" -) - -type clientTally struct { - queryCount tally.Counter - queryFailCount tally.Counter - queryTimer tally.Timer - - executeCount tally.Counter - executeFailCount tally.Counter - executeTimer tally.Timer -} - -func newClientTally(channelContext context.Channel) clientTally { - return clientTally{ - queryCount: metrics.RootScope.SubScope(channelContext.ChannelID()).Counter("ch_client_query_calls"), - queryFailCount: metrics.RootScope.SubScope(channelContext.ChannelID()).Counter("ch_client_query_errors"), - queryTimer: metrics.RootScope.SubScope(channelContext.ChannelID()).Timer("ch_client_query_processing_time_seconds"), - - executeCount: metrics.RootScope.SubScope(channelContext.ChannelID()).Counter("ch_client_execute_calls"), - executeFailCount: metrics.RootScope.SubScope(channelContext.ChannelID()).Counter("ch_client_execute_errors"), - executeTimer: metrics.RootScope.SubScope(channelContext.ChannelID()).Timer("ch_client_execute_processing_time_seconds"), - } -} - -func newClient(channelContext context.Channel, membership fab.ChannelMembership, eventService fab.EventService, greylistProvider *greylist.Filter) Client { - ct := newClientTally(channelContext) - - channelClient := Client{ - membership: membership, - eventService: eventService, - greylist: greylistProvider, - context: channelContext, - clientTally: ct, - } - return channelClient -} - -func callQuery(cc *Client, request Request, options ...RequestOption) (Response, error) { - cc.executeCount.Inc(1) - stopWatch := cc.queryTimer.Start() - defer stopWatch.Stop() - - r, err := cc.InvokeHandler(invoke.NewQueryHandler(), request, options...) - if err != nil { - cc.queryFailCount.Inc(1) - } - return r, err -} - -func callExecute(cc *Client, request Request, options ...RequestOption) (Response, error) { - cc.executeCount.Inc(1) - stopWatch := cc.executeTimer.Start() - defer stopWatch.Stop() - - r, err := cc.InvokeHandler(invoke.NewExecuteHandler(), request, options...) - if err != nil { - cc.executeFailCount.Inc(1) - } - return r, err -} diff --git a/pkg/client/channel/example_test.go b/pkg/client/channel/example_test.go index e802d09075..f512a0a952 100644 --- a/pkg/client/channel/example_test.go +++ b/pkg/client/channel/example_test.go @@ -14,7 +14,6 @@ import ( ) func Example() { - c, err := New(mockChannelProvider("mychannel")) if err != nil { fmt.Println("failed to create client") @@ -31,7 +30,6 @@ func Example() { } func ExampleNew() { - ctx := mockChannelProvider("mychannel") c, err := New(ctx) @@ -50,7 +48,6 @@ func ExampleNew() { } func ExampleClient_Query() { - c, err := New(mockChannelProvider("mychannel")) if err != nil { fmt.Println("failed to create client") @@ -69,7 +66,6 @@ func ExampleClient_Query() { } func ExampleClient_Execute() { - c, err := New(mockChannelProvider("mychannel")) if err != nil { fmt.Println("failed to create client") @@ -86,7 +82,6 @@ func ExampleClient_Execute() { } func ExampleClient_RegisterChaincodeEvent() { - c, err := New(mockChannelProvider("mychannel")) if err != nil { fmt.Println("failed to create client") @@ -105,7 +100,6 @@ func ExampleClient_RegisterChaincodeEvent() { } func ExampleClient_InvokeHandler() { - c, err := New(mockChannelProvider("mychannel")) if err != nil { fmt.Println("failed to create client") diff --git a/pkg/common/providers/fab/provider.go b/pkg/common/providers/fab/provider.go index a1f5525c52..fb6005a845 100644 --- a/pkg/common/providers/fab/provider.go +++ b/pkg/common/providers/fab/provider.go @@ -10,13 +10,12 @@ import ( reqContext "context" "crypto/tls" "crypto/x509" - - "github.com/hyperledger/fabric-sdk-go/pkg/common/options" - "time" + "github.com/hyperledger/fabric-sdk-go/pkg/common/options" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" + "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" "google.golang.org/grpc" ) @@ -155,6 +154,7 @@ type Providers interface { ChannelProvider() ChannelProvider InfraProvider() InfraProvider EndpointConfig() EndpointConfig + MetricsProvider } // CertPool is a thread safe wrapper around the x509 standard library @@ -166,3 +166,8 @@ type CertPool interface { //Call Get() after Add() to get the updated certpool Add(certs ...*x509.Certificate) } + +// MetricsProvider represents a provider of metrics. +type MetricsProvider interface { + GetMetrics() *metrics.ClientMetrics +} diff --git a/pkg/common/providers/test/mockcontext/mockcontext.gen.go b/pkg/common/providers/test/mockcontext/mockcontext.gen.go index 2a6d9f7c72..a75076f033 100644 --- a/pkg/common/providers/test/mockcontext/mockcontext.gen.go +++ b/pkg/common/providers/test/mockcontext/mockcontext.gen.go @@ -11,6 +11,7 @@ import ( core "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" fab "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" msp "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" + metrics "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" ) // MockProviders is a mock of Providers interface @@ -38,6 +39,7 @@ func (m *MockProviders) EXPECT() *MockProvidersMockRecorder { // ChannelProvider mocks base method func (m *MockProviders) ChannelProvider() fab.ChannelProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChannelProvider") ret0, _ := ret[0].(fab.ChannelProvider) return ret0 @@ -45,11 +47,13 @@ func (m *MockProviders) ChannelProvider() fab.ChannelProvider { // ChannelProvider indicates an expected call of ChannelProvider func (mr *MockProvidersMockRecorder) ChannelProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChannelProvider", reflect.TypeOf((*MockProviders)(nil).ChannelProvider)) } // CryptoSuite mocks base method func (m *MockProviders) CryptoSuite() core.CryptoSuite { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CryptoSuite") ret0, _ := ret[0].(core.CryptoSuite) return ret0 @@ -57,11 +61,13 @@ func (m *MockProviders) CryptoSuite() core.CryptoSuite { // CryptoSuite indicates an expected call of CryptoSuite func (mr *MockProvidersMockRecorder) CryptoSuite() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuite", reflect.TypeOf((*MockProviders)(nil).CryptoSuite)) } // EndpointConfig mocks base method func (m *MockProviders) EndpointConfig() fab.EndpointConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EndpointConfig") ret0, _ := ret[0].(fab.EndpointConfig) return ret0 @@ -69,11 +75,27 @@ func (m *MockProviders) EndpointConfig() fab.EndpointConfig { // EndpointConfig indicates an expected call of EndpointConfig func (mr *MockProvidersMockRecorder) EndpointConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EndpointConfig", reflect.TypeOf((*MockProviders)(nil).EndpointConfig)) } +// GetMetrics mocks base method +func (m *MockProviders) GetMetrics() *metrics.ClientMetrics { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMetrics") + ret0, _ := ret[0].(*metrics.ClientMetrics) + return ret0 +} + +// GetMetrics indicates an expected call of GetMetrics +func (mr *MockProvidersMockRecorder) GetMetrics() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMetrics", reflect.TypeOf((*MockProviders)(nil).GetMetrics)) +} + // IdentityConfig mocks base method func (m *MockProviders) IdentityConfig() msp.IdentityConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IdentityConfig") ret0, _ := ret[0].(msp.IdentityConfig) return ret0 @@ -81,11 +103,13 @@ func (m *MockProviders) IdentityConfig() msp.IdentityConfig { // IdentityConfig indicates an expected call of IdentityConfig func (mr *MockProvidersMockRecorder) IdentityConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityConfig", reflect.TypeOf((*MockProviders)(nil).IdentityConfig)) } // IdentityManager mocks base method func (m *MockProviders) IdentityManager(arg0 string) (msp.IdentityManager, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IdentityManager", arg0) ret0, _ := ret[0].(msp.IdentityManager) ret1, _ := ret[1].(bool) @@ -94,11 +118,13 @@ func (m *MockProviders) IdentityManager(arg0 string) (msp.IdentityManager, bool) // IdentityManager indicates an expected call of IdentityManager func (mr *MockProvidersMockRecorder) IdentityManager(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityManager", reflect.TypeOf((*MockProviders)(nil).IdentityManager), arg0) } // InfraProvider mocks base method func (m *MockProviders) InfraProvider() fab.InfraProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "InfraProvider") ret0, _ := ret[0].(fab.InfraProvider) return ret0 @@ -106,11 +132,13 @@ func (m *MockProviders) InfraProvider() fab.InfraProvider { // InfraProvider indicates an expected call of InfraProvider func (mr *MockProvidersMockRecorder) InfraProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InfraProvider", reflect.TypeOf((*MockProviders)(nil).InfraProvider)) } // LocalDiscoveryProvider mocks base method func (m *MockProviders) LocalDiscoveryProvider() fab.LocalDiscoveryProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LocalDiscoveryProvider") ret0, _ := ret[0].(fab.LocalDiscoveryProvider) return ret0 @@ -118,11 +146,13 @@ func (m *MockProviders) LocalDiscoveryProvider() fab.LocalDiscoveryProvider { // LocalDiscoveryProvider indicates an expected call of LocalDiscoveryProvider func (mr *MockProvidersMockRecorder) LocalDiscoveryProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LocalDiscoveryProvider", reflect.TypeOf((*MockProviders)(nil).LocalDiscoveryProvider)) } // SigningManager mocks base method func (m *MockProviders) SigningManager() core.SigningManager { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SigningManager") ret0, _ := ret[0].(core.SigningManager) return ret0 @@ -130,11 +160,13 @@ func (m *MockProviders) SigningManager() core.SigningManager { // SigningManager indicates an expected call of SigningManager func (mr *MockProvidersMockRecorder) SigningManager() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SigningManager", reflect.TypeOf((*MockProviders)(nil).SigningManager)) } // UserStore mocks base method func (m *MockProviders) UserStore() msp.UserStore { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UserStore") ret0, _ := ret[0].(msp.UserStore) return ret0 @@ -142,6 +174,7 @@ func (m *MockProviders) UserStore() msp.UserStore { // UserStore indicates an expected call of UserStore func (mr *MockProvidersMockRecorder) UserStore() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserStore", reflect.TypeOf((*MockProviders)(nil).UserStore)) } @@ -170,6 +203,7 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder { // ChannelProvider mocks base method func (m *MockClient) ChannelProvider() fab.ChannelProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChannelProvider") ret0, _ := ret[0].(fab.ChannelProvider) return ret0 @@ -177,11 +211,13 @@ func (m *MockClient) ChannelProvider() fab.ChannelProvider { // ChannelProvider indicates an expected call of ChannelProvider func (mr *MockClientMockRecorder) ChannelProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChannelProvider", reflect.TypeOf((*MockClient)(nil).ChannelProvider)) } // CryptoSuite mocks base method func (m *MockClient) CryptoSuite() core.CryptoSuite { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CryptoSuite") ret0, _ := ret[0].(core.CryptoSuite) return ret0 @@ -189,11 +225,13 @@ func (m *MockClient) CryptoSuite() core.CryptoSuite { // CryptoSuite indicates an expected call of CryptoSuite func (mr *MockClientMockRecorder) CryptoSuite() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuite", reflect.TypeOf((*MockClient)(nil).CryptoSuite)) } // EndpointConfig mocks base method func (m *MockClient) EndpointConfig() fab.EndpointConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EndpointConfig") ret0, _ := ret[0].(fab.EndpointConfig) return ret0 @@ -201,11 +239,13 @@ func (m *MockClient) EndpointConfig() fab.EndpointConfig { // EndpointConfig indicates an expected call of EndpointConfig func (mr *MockClientMockRecorder) EndpointConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EndpointConfig", reflect.TypeOf((*MockClient)(nil).EndpointConfig)) } // EnrollmentCertificate mocks base method func (m *MockClient) EnrollmentCertificate() []byte { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EnrollmentCertificate") ret0, _ := ret[0].([]byte) return ret0 @@ -213,11 +253,27 @@ func (m *MockClient) EnrollmentCertificate() []byte { // EnrollmentCertificate indicates an expected call of EnrollmentCertificate func (mr *MockClientMockRecorder) EnrollmentCertificate() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnrollmentCertificate", reflect.TypeOf((*MockClient)(nil).EnrollmentCertificate)) } +// GetMetrics mocks base method +func (m *MockClient) GetMetrics() *metrics.ClientMetrics { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMetrics") + ret0, _ := ret[0].(*metrics.ClientMetrics) + return ret0 +} + +// GetMetrics indicates an expected call of GetMetrics +func (mr *MockClientMockRecorder) GetMetrics() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMetrics", reflect.TypeOf((*MockClient)(nil).GetMetrics)) +} + // Identifier mocks base method func (m *MockClient) Identifier() *msp.IdentityIdentifier { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Identifier") ret0, _ := ret[0].(*msp.IdentityIdentifier) return ret0 @@ -225,11 +281,13 @@ func (m *MockClient) Identifier() *msp.IdentityIdentifier { // Identifier indicates an expected call of Identifier func (mr *MockClientMockRecorder) Identifier() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Identifier", reflect.TypeOf((*MockClient)(nil).Identifier)) } // IdentityConfig mocks base method func (m *MockClient) IdentityConfig() msp.IdentityConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IdentityConfig") ret0, _ := ret[0].(msp.IdentityConfig) return ret0 @@ -237,11 +295,13 @@ func (m *MockClient) IdentityConfig() msp.IdentityConfig { // IdentityConfig indicates an expected call of IdentityConfig func (mr *MockClientMockRecorder) IdentityConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityConfig", reflect.TypeOf((*MockClient)(nil).IdentityConfig)) } // IdentityManager mocks base method func (m *MockClient) IdentityManager(arg0 string) (msp.IdentityManager, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IdentityManager", arg0) ret0, _ := ret[0].(msp.IdentityManager) ret1, _ := ret[1].(bool) @@ -250,11 +310,13 @@ func (m *MockClient) IdentityManager(arg0 string) (msp.IdentityManager, bool) { // IdentityManager indicates an expected call of IdentityManager func (mr *MockClientMockRecorder) IdentityManager(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityManager", reflect.TypeOf((*MockClient)(nil).IdentityManager), arg0) } // InfraProvider mocks base method func (m *MockClient) InfraProvider() fab.InfraProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "InfraProvider") ret0, _ := ret[0].(fab.InfraProvider) return ret0 @@ -262,11 +324,13 @@ func (m *MockClient) InfraProvider() fab.InfraProvider { // InfraProvider indicates an expected call of InfraProvider func (mr *MockClientMockRecorder) InfraProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InfraProvider", reflect.TypeOf((*MockClient)(nil).InfraProvider)) } // LocalDiscoveryProvider mocks base method func (m *MockClient) LocalDiscoveryProvider() fab.LocalDiscoveryProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LocalDiscoveryProvider") ret0, _ := ret[0].(fab.LocalDiscoveryProvider) return ret0 @@ -274,11 +338,13 @@ func (m *MockClient) LocalDiscoveryProvider() fab.LocalDiscoveryProvider { // LocalDiscoveryProvider indicates an expected call of LocalDiscoveryProvider func (mr *MockClientMockRecorder) LocalDiscoveryProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LocalDiscoveryProvider", reflect.TypeOf((*MockClient)(nil).LocalDiscoveryProvider)) } // PrivateKey mocks base method func (m *MockClient) PrivateKey() core.Key { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PrivateKey") ret0, _ := ret[0].(core.Key) return ret0 @@ -286,11 +352,13 @@ func (m *MockClient) PrivateKey() core.Key { // PrivateKey indicates an expected call of PrivateKey func (mr *MockClientMockRecorder) PrivateKey() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrivateKey", reflect.TypeOf((*MockClient)(nil).PrivateKey)) } // PublicVersion mocks base method func (m *MockClient) PublicVersion() msp.Identity { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PublicVersion") ret0, _ := ret[0].(msp.Identity) return ret0 @@ -298,11 +366,13 @@ func (m *MockClient) PublicVersion() msp.Identity { // PublicVersion indicates an expected call of PublicVersion func (mr *MockClientMockRecorder) PublicVersion() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublicVersion", reflect.TypeOf((*MockClient)(nil).PublicVersion)) } // Serialize mocks base method func (m *MockClient) Serialize() ([]byte, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Serialize") ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) @@ -311,11 +381,13 @@ func (m *MockClient) Serialize() ([]byte, error) { // Serialize indicates an expected call of Serialize func (mr *MockClientMockRecorder) Serialize() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Serialize", reflect.TypeOf((*MockClient)(nil).Serialize)) } // Sign mocks base method func (m *MockClient) Sign(arg0 []byte) ([]byte, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Sign", arg0) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) @@ -324,11 +396,13 @@ func (m *MockClient) Sign(arg0 []byte) ([]byte, error) { // Sign indicates an expected call of Sign func (mr *MockClientMockRecorder) Sign(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sign", reflect.TypeOf((*MockClient)(nil).Sign), arg0) } // SigningManager mocks base method func (m *MockClient) SigningManager() core.SigningManager { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SigningManager") ret0, _ := ret[0].(core.SigningManager) return ret0 @@ -336,11 +410,13 @@ func (m *MockClient) SigningManager() core.SigningManager { // SigningManager indicates an expected call of SigningManager func (mr *MockClientMockRecorder) SigningManager() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SigningManager", reflect.TypeOf((*MockClient)(nil).SigningManager)) } // UserStore mocks base method func (m *MockClient) UserStore() msp.UserStore { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UserStore") ret0, _ := ret[0].(msp.UserStore) return ret0 @@ -348,11 +424,13 @@ func (m *MockClient) UserStore() msp.UserStore { // UserStore indicates an expected call of UserStore func (mr *MockClientMockRecorder) UserStore() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserStore", reflect.TypeOf((*MockClient)(nil).UserStore)) } // Verify mocks base method func (m *MockClient) Verify(arg0, arg1 []byte) error { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Verify", arg0, arg1) ret0, _ := ret[0].(error) return ret0 @@ -360,5 +438,6 @@ func (m *MockClient) Verify(arg0, arg1 []byte) error { // Verify indicates an expected call of Verify func (mr *MockClientMockRecorder) Verify(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockClient)(nil).Verify), arg0, arg1) } diff --git a/pkg/common/providers/test/mockcore/mockcore.gen.go b/pkg/common/providers/test/mockcore/mockcore.gen.go index e9ef63837a..c145c039a1 100644 --- a/pkg/common/providers/test/mockcore/mockcore.gen.go +++ b/pkg/common/providers/test/mockcore/mockcore.gen.go @@ -36,6 +36,7 @@ func (m *MockCryptoSuiteConfig) EXPECT() *MockCryptoSuiteConfigMockRecorder { // IsSecurityEnabled mocks base method func (m *MockCryptoSuiteConfig) IsSecurityEnabled() bool { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IsSecurityEnabled") ret0, _ := ret[0].(bool) return ret0 @@ -43,11 +44,13 @@ func (m *MockCryptoSuiteConfig) IsSecurityEnabled() bool { // IsSecurityEnabled indicates an expected call of IsSecurityEnabled func (mr *MockCryptoSuiteConfigMockRecorder) IsSecurityEnabled() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSecurityEnabled", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).IsSecurityEnabled)) } // KeyStorePath mocks base method func (m *MockCryptoSuiteConfig) KeyStorePath() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "KeyStorePath") ret0, _ := ret[0].(string) return ret0 @@ -55,11 +58,13 @@ func (m *MockCryptoSuiteConfig) KeyStorePath() string { // KeyStorePath indicates an expected call of KeyStorePath func (mr *MockCryptoSuiteConfigMockRecorder) KeyStorePath() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeyStorePath", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).KeyStorePath)) } // SecurityAlgorithm mocks base method func (m *MockCryptoSuiteConfig) SecurityAlgorithm() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SecurityAlgorithm") ret0, _ := ret[0].(string) return ret0 @@ -67,11 +72,13 @@ func (m *MockCryptoSuiteConfig) SecurityAlgorithm() string { // SecurityAlgorithm indicates an expected call of SecurityAlgorithm func (mr *MockCryptoSuiteConfigMockRecorder) SecurityAlgorithm() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SecurityAlgorithm", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).SecurityAlgorithm)) } // SecurityLevel mocks base method func (m *MockCryptoSuiteConfig) SecurityLevel() int { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SecurityLevel") ret0, _ := ret[0].(int) return ret0 @@ -79,11 +86,13 @@ func (m *MockCryptoSuiteConfig) SecurityLevel() int { // SecurityLevel indicates an expected call of SecurityLevel func (mr *MockCryptoSuiteConfigMockRecorder) SecurityLevel() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SecurityLevel", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).SecurityLevel)) } // SecurityProvider mocks base method func (m *MockCryptoSuiteConfig) SecurityProvider() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SecurityProvider") ret0, _ := ret[0].(string) return ret0 @@ -91,11 +100,13 @@ func (m *MockCryptoSuiteConfig) SecurityProvider() string { // SecurityProvider indicates an expected call of SecurityProvider func (mr *MockCryptoSuiteConfigMockRecorder) SecurityProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SecurityProvider", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).SecurityProvider)) } // SecurityProviderLabel mocks base method func (m *MockCryptoSuiteConfig) SecurityProviderLabel() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SecurityProviderLabel") ret0, _ := ret[0].(string) return ret0 @@ -103,11 +114,13 @@ func (m *MockCryptoSuiteConfig) SecurityProviderLabel() string { // SecurityProviderLabel indicates an expected call of SecurityProviderLabel func (mr *MockCryptoSuiteConfigMockRecorder) SecurityProviderLabel() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SecurityProviderLabel", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).SecurityProviderLabel)) } // SecurityProviderLibPath mocks base method func (m *MockCryptoSuiteConfig) SecurityProviderLibPath() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SecurityProviderLibPath") ret0, _ := ret[0].(string) return ret0 @@ -115,11 +128,13 @@ func (m *MockCryptoSuiteConfig) SecurityProviderLibPath() string { // SecurityProviderLibPath indicates an expected call of SecurityProviderLibPath func (mr *MockCryptoSuiteConfigMockRecorder) SecurityProviderLibPath() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SecurityProviderLibPath", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).SecurityProviderLibPath)) } // SecurityProviderPin mocks base method func (m *MockCryptoSuiteConfig) SecurityProviderPin() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SecurityProviderPin") ret0, _ := ret[0].(string) return ret0 @@ -127,11 +142,13 @@ func (m *MockCryptoSuiteConfig) SecurityProviderPin() string { // SecurityProviderPin indicates an expected call of SecurityProviderPin func (mr *MockCryptoSuiteConfigMockRecorder) SecurityProviderPin() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SecurityProviderPin", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).SecurityProviderPin)) } // SoftVerify mocks base method func (m *MockCryptoSuiteConfig) SoftVerify() bool { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SoftVerify") ret0, _ := ret[0].(bool) return ret0 @@ -139,6 +156,7 @@ func (m *MockCryptoSuiteConfig) SoftVerify() bool { // SoftVerify indicates an expected call of SoftVerify func (mr *MockCryptoSuiteConfigMockRecorder) SoftVerify() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SoftVerify", reflect.TypeOf((*MockCryptoSuiteConfig)(nil).SoftVerify)) } @@ -167,6 +185,7 @@ func (m *MockConfigBackend) EXPECT() *MockConfigBackendMockRecorder { // Lookup mocks base method func (m *MockConfigBackend) Lookup(arg0 string) (interface{}, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Lookup", arg0) ret0, _ := ret[0].(interface{}) ret1, _ := ret[1].(bool) @@ -175,6 +194,7 @@ func (m *MockConfigBackend) Lookup(arg0 string) (interface{}, bool) { // Lookup indicates an expected call of Lookup func (mr *MockConfigBackendMockRecorder) Lookup(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lookup", reflect.TypeOf((*MockConfigBackend)(nil).Lookup), arg0) } @@ -203,6 +223,7 @@ func (m *MockProviders) EXPECT() *MockProvidersMockRecorder { // CryptoSuite mocks base method func (m *MockProviders) CryptoSuite() core.CryptoSuite { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CryptoSuite") ret0, _ := ret[0].(core.CryptoSuite) return ret0 @@ -210,11 +231,13 @@ func (m *MockProviders) CryptoSuite() core.CryptoSuite { // CryptoSuite indicates an expected call of CryptoSuite func (mr *MockProvidersMockRecorder) CryptoSuite() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoSuite", reflect.TypeOf((*MockProviders)(nil).CryptoSuite)) } // SigningManager mocks base method func (m *MockProviders) SigningManager() core.SigningManager { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SigningManager") ret0, _ := ret[0].(core.SigningManager) return ret0 @@ -222,5 +245,6 @@ func (m *MockProviders) SigningManager() core.SigningManager { // SigningManager indicates an expected call of SigningManager func (mr *MockProvidersMockRecorder) SigningManager() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SigningManager", reflect.TypeOf((*MockProviders)(nil).SigningManager)) } diff --git a/pkg/common/providers/test/mockfab/mockfab.gen.go b/pkg/common/providers/test/mockfab/mockfab.gen.go index 574abfca7b..088a2547b8 100644 --- a/pkg/common/providers/test/mockfab/mockfab.gen.go +++ b/pkg/common/providers/test/mockfab/mockfab.gen.go @@ -12,6 +12,7 @@ import ( gomock "github.com/golang/mock/gomock" fab "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" + metrics "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" ) // MockEndpointConfig is a mock of EndpointConfig interface @@ -39,6 +40,7 @@ func (m *MockEndpointConfig) EXPECT() *MockEndpointConfigMockRecorder { // ChannelConfig mocks base method func (m *MockEndpointConfig) ChannelConfig(arg0 string) *fab.ChannelEndpointConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChannelConfig", arg0) ret0, _ := ret[0].(*fab.ChannelEndpointConfig) return ret0 @@ -46,11 +48,13 @@ func (m *MockEndpointConfig) ChannelConfig(arg0 string) *fab.ChannelEndpointConf // ChannelConfig indicates an expected call of ChannelConfig func (mr *MockEndpointConfigMockRecorder) ChannelConfig(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChannelConfig", reflect.TypeOf((*MockEndpointConfig)(nil).ChannelConfig), arg0) } // ChannelOrderers mocks base method func (m *MockEndpointConfig) ChannelOrderers(arg0 string) []fab.OrdererConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChannelOrderers", arg0) ret0, _ := ret[0].([]fab.OrdererConfig) return ret0 @@ -58,11 +62,13 @@ func (m *MockEndpointConfig) ChannelOrderers(arg0 string) []fab.OrdererConfig { // ChannelOrderers indicates an expected call of ChannelOrderers func (mr *MockEndpointConfigMockRecorder) ChannelOrderers(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChannelOrderers", reflect.TypeOf((*MockEndpointConfig)(nil).ChannelOrderers), arg0) } // ChannelPeers mocks base method func (m *MockEndpointConfig) ChannelPeers(arg0 string) []fab.ChannelPeer { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChannelPeers", arg0) ret0, _ := ret[0].([]fab.ChannelPeer) return ret0 @@ -70,11 +76,13 @@ func (m *MockEndpointConfig) ChannelPeers(arg0 string) []fab.ChannelPeer { // ChannelPeers indicates an expected call of ChannelPeers func (mr *MockEndpointConfigMockRecorder) ChannelPeers(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChannelPeers", reflect.TypeOf((*MockEndpointConfig)(nil).ChannelPeers), arg0) } // CryptoConfigPath mocks base method func (m *MockEndpointConfig) CryptoConfigPath() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CryptoConfigPath") ret0, _ := ret[0].(string) return ret0 @@ -82,11 +90,13 @@ func (m *MockEndpointConfig) CryptoConfigPath() string { // CryptoConfigPath indicates an expected call of CryptoConfigPath func (mr *MockEndpointConfigMockRecorder) CryptoConfigPath() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CryptoConfigPath", reflect.TypeOf((*MockEndpointConfig)(nil).CryptoConfigPath)) } // NetworkConfig mocks base method func (m *MockEndpointConfig) NetworkConfig() *fab.NetworkConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NetworkConfig") ret0, _ := ret[0].(*fab.NetworkConfig) return ret0 @@ -94,11 +104,13 @@ func (m *MockEndpointConfig) NetworkConfig() *fab.NetworkConfig { // NetworkConfig indicates an expected call of NetworkConfig func (mr *MockEndpointConfigMockRecorder) NetworkConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetworkConfig", reflect.TypeOf((*MockEndpointConfig)(nil).NetworkConfig)) } // NetworkPeers mocks base method func (m *MockEndpointConfig) NetworkPeers() []fab.NetworkPeer { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "NetworkPeers") ret0, _ := ret[0].([]fab.NetworkPeer) return ret0 @@ -106,11 +118,13 @@ func (m *MockEndpointConfig) NetworkPeers() []fab.NetworkPeer { // NetworkPeers indicates an expected call of NetworkPeers func (mr *MockEndpointConfigMockRecorder) NetworkPeers() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetworkPeers", reflect.TypeOf((*MockEndpointConfig)(nil).NetworkPeers)) } // OrdererConfig mocks base method func (m *MockEndpointConfig) OrdererConfig(arg0 string) (*fab.OrdererConfig, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "OrdererConfig", arg0) ret0, _ := ret[0].(*fab.OrdererConfig) ret1, _ := ret[1].(bool) @@ -119,11 +133,13 @@ func (m *MockEndpointConfig) OrdererConfig(arg0 string) (*fab.OrdererConfig, boo // OrdererConfig indicates an expected call of OrdererConfig func (mr *MockEndpointConfigMockRecorder) OrdererConfig(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrdererConfig", reflect.TypeOf((*MockEndpointConfig)(nil).OrdererConfig), arg0) } // OrderersConfig mocks base method func (m *MockEndpointConfig) OrderersConfig() []fab.OrdererConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "OrderersConfig") ret0, _ := ret[0].([]fab.OrdererConfig) return ret0 @@ -131,11 +147,13 @@ func (m *MockEndpointConfig) OrderersConfig() []fab.OrdererConfig { // OrderersConfig indicates an expected call of OrderersConfig func (mr *MockEndpointConfigMockRecorder) OrderersConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrderersConfig", reflect.TypeOf((*MockEndpointConfig)(nil).OrderersConfig)) } // PeerConfig mocks base method func (m *MockEndpointConfig) PeerConfig(arg0 string) (*fab.PeerConfig, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PeerConfig", arg0) ret0, _ := ret[0].(*fab.PeerConfig) ret1, _ := ret[1].(bool) @@ -144,11 +162,13 @@ func (m *MockEndpointConfig) PeerConfig(arg0 string) (*fab.PeerConfig, bool) { // PeerConfig indicates an expected call of PeerConfig func (mr *MockEndpointConfigMockRecorder) PeerConfig(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerConfig", reflect.TypeOf((*MockEndpointConfig)(nil).PeerConfig), arg0) } // PeersConfig mocks base method func (m *MockEndpointConfig) PeersConfig(arg0 string) ([]fab.PeerConfig, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PeersConfig", arg0) ret0, _ := ret[0].([]fab.PeerConfig) ret1, _ := ret[1].(bool) @@ -157,11 +177,13 @@ func (m *MockEndpointConfig) PeersConfig(arg0 string) ([]fab.PeerConfig, bool) { // PeersConfig indicates an expected call of PeersConfig func (mr *MockEndpointConfigMockRecorder) PeersConfig(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeersConfig", reflect.TypeOf((*MockEndpointConfig)(nil).PeersConfig), arg0) } // TLSCACertPool mocks base method func (m *MockEndpointConfig) TLSCACertPool() fab.CertPool { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TLSCACertPool") ret0, _ := ret[0].(fab.CertPool) return ret0 @@ -169,11 +191,13 @@ func (m *MockEndpointConfig) TLSCACertPool() fab.CertPool { // TLSCACertPool indicates an expected call of TLSCACertPool func (mr *MockEndpointConfigMockRecorder) TLSCACertPool() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TLSCACertPool", reflect.TypeOf((*MockEndpointConfig)(nil).TLSCACertPool)) } // TLSClientCerts mocks base method func (m *MockEndpointConfig) TLSClientCerts() []tls.Certificate { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TLSClientCerts") ret0, _ := ret[0].([]tls.Certificate) return ret0 @@ -181,11 +205,13 @@ func (m *MockEndpointConfig) TLSClientCerts() []tls.Certificate { // TLSClientCerts indicates an expected call of TLSClientCerts func (mr *MockEndpointConfigMockRecorder) TLSClientCerts() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TLSClientCerts", reflect.TypeOf((*MockEndpointConfig)(nil).TLSClientCerts)) } // Timeout mocks base method func (m *MockEndpointConfig) Timeout(arg0 fab.TimeoutType) time.Duration { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Timeout", arg0) ret0, _ := ret[0].(time.Duration) return ret0 @@ -193,6 +219,7 @@ func (m *MockEndpointConfig) Timeout(arg0 fab.TimeoutType) time.Duration { // Timeout indicates an expected call of Timeout func (mr *MockEndpointConfigMockRecorder) Timeout(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Timeout", reflect.TypeOf((*MockEndpointConfig)(nil).Timeout), arg0) } @@ -221,6 +248,7 @@ func (m *MockProposalProcessor) EXPECT() *MockProposalProcessorMockRecorder { // ProcessTransactionProposal mocks base method func (m *MockProposalProcessor) ProcessTransactionProposal(arg0 context.Context, arg1 fab.ProcessProposalRequest) (*fab.TransactionProposalResponse, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ProcessTransactionProposal", arg0, arg1) ret0, _ := ret[0].(*fab.TransactionProposalResponse) ret1, _ := ret[1].(error) @@ -229,6 +257,7 @@ func (m *MockProposalProcessor) ProcessTransactionProposal(arg0 context.Context, // ProcessTransactionProposal indicates an expected call of ProcessTransactionProposal func (mr *MockProposalProcessorMockRecorder) ProcessTransactionProposal(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessTransactionProposal", reflect.TypeOf((*MockProposalProcessor)(nil).ProcessTransactionProposal), arg0, arg1) } @@ -257,6 +286,7 @@ func (m *MockProviders) EXPECT() *MockProvidersMockRecorder { // ChannelProvider mocks base method func (m *MockProviders) ChannelProvider() fab.ChannelProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ChannelProvider") ret0, _ := ret[0].(fab.ChannelProvider) return ret0 @@ -264,11 +294,13 @@ func (m *MockProviders) ChannelProvider() fab.ChannelProvider { // ChannelProvider indicates an expected call of ChannelProvider func (mr *MockProvidersMockRecorder) ChannelProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChannelProvider", reflect.TypeOf((*MockProviders)(nil).ChannelProvider)) } // EndpointConfig mocks base method func (m *MockProviders) EndpointConfig() fab.EndpointConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EndpointConfig") ret0, _ := ret[0].(fab.EndpointConfig) return ret0 @@ -276,11 +308,27 @@ func (m *MockProviders) EndpointConfig() fab.EndpointConfig { // EndpointConfig indicates an expected call of EndpointConfig func (mr *MockProvidersMockRecorder) EndpointConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EndpointConfig", reflect.TypeOf((*MockProviders)(nil).EndpointConfig)) } +// GetMetrics mocks base method +func (m *MockProviders) GetMetrics() *metrics.ClientMetrics { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMetrics") + ret0, _ := ret[0].(*metrics.ClientMetrics) + return ret0 +} + +// GetMetrics indicates an expected call of GetMetrics +func (mr *MockProvidersMockRecorder) GetMetrics() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMetrics", reflect.TypeOf((*MockProviders)(nil).GetMetrics)) +} + // InfraProvider mocks base method func (m *MockProviders) InfraProvider() fab.InfraProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "InfraProvider") ret0, _ := ret[0].(fab.InfraProvider) return ret0 @@ -288,11 +336,13 @@ func (m *MockProviders) InfraProvider() fab.InfraProvider { // InfraProvider indicates an expected call of InfraProvider func (mr *MockProvidersMockRecorder) InfraProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InfraProvider", reflect.TypeOf((*MockProviders)(nil).InfraProvider)) } // LocalDiscoveryProvider mocks base method func (m *MockProviders) LocalDiscoveryProvider() fab.LocalDiscoveryProvider { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LocalDiscoveryProvider") ret0, _ := ret[0].(fab.LocalDiscoveryProvider) return ret0 @@ -300,5 +350,6 @@ func (m *MockProviders) LocalDiscoveryProvider() fab.LocalDiscoveryProvider { // LocalDiscoveryProvider indicates an expected call of LocalDiscoveryProvider func (mr *MockProvidersMockRecorder) LocalDiscoveryProvider() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LocalDiscoveryProvider", reflect.TypeOf((*MockProviders)(nil).LocalDiscoveryProvider)) } diff --git a/pkg/common/providers/test/mockmsp/mockmsp.gen.go b/pkg/common/providers/test/mockmsp/mockmsp.gen.go index 396f7889c1..50c79c08ed 100644 --- a/pkg/common/providers/test/mockmsp/mockmsp.gen.go +++ b/pkg/common/providers/test/mockmsp/mockmsp.gen.go @@ -36,6 +36,7 @@ func (m *MockIdentityConfig) EXPECT() *MockIdentityConfigMockRecorder { // CAClientCert mocks base method func (m *MockIdentityConfig) CAClientCert(arg0 string) ([]byte, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CAClientCert", arg0) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(bool) @@ -44,11 +45,13 @@ func (m *MockIdentityConfig) CAClientCert(arg0 string) ([]byte, bool) { // CAClientCert indicates an expected call of CAClientCert func (mr *MockIdentityConfigMockRecorder) CAClientCert(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CAClientCert", reflect.TypeOf((*MockIdentityConfig)(nil).CAClientCert), arg0) } // CAClientKey mocks base method func (m *MockIdentityConfig) CAClientKey(arg0 string) ([]byte, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CAClientKey", arg0) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(bool) @@ -57,11 +60,13 @@ func (m *MockIdentityConfig) CAClientKey(arg0 string) ([]byte, bool) { // CAClientKey indicates an expected call of CAClientKey func (mr *MockIdentityConfigMockRecorder) CAClientKey(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CAClientKey", reflect.TypeOf((*MockIdentityConfig)(nil).CAClientKey), arg0) } // CAConfig mocks base method func (m *MockIdentityConfig) CAConfig(arg0 string) (*msp.CAConfig, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CAConfig", arg0) ret0, _ := ret[0].(*msp.CAConfig) ret1, _ := ret[1].(bool) @@ -70,11 +75,13 @@ func (m *MockIdentityConfig) CAConfig(arg0 string) (*msp.CAConfig, bool) { // CAConfig indicates an expected call of CAConfig func (mr *MockIdentityConfigMockRecorder) CAConfig(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CAConfig", reflect.TypeOf((*MockIdentityConfig)(nil).CAConfig), arg0) } // CAKeyStorePath mocks base method func (m *MockIdentityConfig) CAKeyStorePath() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CAKeyStorePath") ret0, _ := ret[0].(string) return ret0 @@ -82,11 +89,13 @@ func (m *MockIdentityConfig) CAKeyStorePath() string { // CAKeyStorePath indicates an expected call of CAKeyStorePath func (mr *MockIdentityConfigMockRecorder) CAKeyStorePath() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CAKeyStorePath", reflect.TypeOf((*MockIdentityConfig)(nil).CAKeyStorePath)) } // CAServerCerts mocks base method func (m *MockIdentityConfig) CAServerCerts(arg0 string) ([][]byte, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CAServerCerts", arg0) ret0, _ := ret[0].([][]byte) ret1, _ := ret[1].(bool) @@ -95,11 +104,13 @@ func (m *MockIdentityConfig) CAServerCerts(arg0 string) ([][]byte, bool) { // CAServerCerts indicates an expected call of CAServerCerts func (mr *MockIdentityConfigMockRecorder) CAServerCerts(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CAServerCerts", reflect.TypeOf((*MockIdentityConfig)(nil).CAServerCerts), arg0) } // Client mocks base method func (m *MockIdentityConfig) Client() *msp.ClientConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Client") ret0, _ := ret[0].(*msp.ClientConfig) return ret0 @@ -107,11 +118,13 @@ func (m *MockIdentityConfig) Client() *msp.ClientConfig { // Client indicates an expected call of Client func (mr *MockIdentityConfigMockRecorder) Client() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Client", reflect.TypeOf((*MockIdentityConfig)(nil).Client)) } // CredentialStorePath mocks base method func (m *MockIdentityConfig) CredentialStorePath() string { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CredentialStorePath") ret0, _ := ret[0].(string) return ret0 @@ -119,6 +132,7 @@ func (m *MockIdentityConfig) CredentialStorePath() string { // CredentialStorePath indicates an expected call of CredentialStorePath func (mr *MockIdentityConfigMockRecorder) CredentialStorePath() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CredentialStorePath", reflect.TypeOf((*MockIdentityConfig)(nil).CredentialStorePath)) } @@ -147,6 +161,7 @@ func (m *MockIdentityManager) EXPECT() *MockIdentityManagerMockRecorder { // CreateSigningIdentity mocks base method func (m *MockIdentityManager) CreateSigningIdentity(arg0 ...msp.SigningIdentityOption) (msp.SigningIdentity, error) { + m.ctrl.T.Helper() varargs := []interface{}{} for _, a := range arg0 { varargs = append(varargs, a) @@ -159,11 +174,13 @@ func (m *MockIdentityManager) CreateSigningIdentity(arg0 ...msp.SigningIdentityO // CreateSigningIdentity indicates an expected call of CreateSigningIdentity func (mr *MockIdentityManagerMockRecorder) CreateSigningIdentity(arg0 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSigningIdentity", reflect.TypeOf((*MockIdentityManager)(nil).CreateSigningIdentity), arg0...) } // GetSigningIdentity mocks base method func (m *MockIdentityManager) GetSigningIdentity(arg0 string) (msp.SigningIdentity, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetSigningIdentity", arg0) ret0, _ := ret[0].(msp.SigningIdentity) ret1, _ := ret[1].(error) @@ -172,6 +189,7 @@ func (m *MockIdentityManager) GetSigningIdentity(arg0 string) (msp.SigningIdenti // GetSigningIdentity indicates an expected call of GetSigningIdentity func (mr *MockIdentityManagerMockRecorder) GetSigningIdentity(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSigningIdentity", reflect.TypeOf((*MockIdentityManager)(nil).GetSigningIdentity), arg0) } @@ -200,6 +218,7 @@ func (m *MockProviders) EXPECT() *MockProvidersMockRecorder { // IdentityConfig mocks base method func (m *MockProviders) IdentityConfig() msp.IdentityConfig { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IdentityConfig") ret0, _ := ret[0].(msp.IdentityConfig) return ret0 @@ -207,11 +226,13 @@ func (m *MockProviders) IdentityConfig() msp.IdentityConfig { // IdentityConfig indicates an expected call of IdentityConfig func (mr *MockProvidersMockRecorder) IdentityConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityConfig", reflect.TypeOf((*MockProviders)(nil).IdentityConfig)) } // IdentityManager mocks base method func (m *MockProviders) IdentityManager(arg0 string) (msp.IdentityManager, bool) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IdentityManager", arg0) ret0, _ := ret[0].(msp.IdentityManager) ret1, _ := ret[1].(bool) @@ -220,11 +241,13 @@ func (m *MockProviders) IdentityManager(arg0 string) (msp.IdentityManager, bool) // IdentityManager indicates an expected call of IdentityManager func (mr *MockProvidersMockRecorder) IdentityManager(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityManager", reflect.TypeOf((*MockProviders)(nil).IdentityManager), arg0) } // UserStore mocks base method func (m *MockProviders) UserStore() msp.UserStore { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UserStore") ret0, _ := ret[0].(msp.UserStore) return ret0 @@ -232,5 +255,6 @@ func (m *MockProviders) UserStore() msp.UserStore { // UserStore indicates an expected call of UserStore func (mr *MockProvidersMockRecorder) UserStore() *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserStore", reflect.TypeOf((*MockProviders)(nil).UserStore)) } diff --git a/pkg/context/context.go b/pkg/context/context.go index c6e2e743a7..895067900c 100644 --- a/pkg/context/context.go +++ b/pkg/context/context.go @@ -17,6 +17,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" + "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" ) // Client supplies the configuration and signing identity to client objects. @@ -43,6 +44,7 @@ type Channel struct { context.Client channelService fab.ChannelService channelID string + metrics *metrics.ClientMetrics } //Providers returns core providers @@ -72,6 +74,7 @@ type Provider struct { idMgmtProvider msp.IdentityManagerProvider infraProvider fab.InfraProvider channelProvider fab.ChannelProvider + clientMetrics *metrics.ClientMetrics } // CryptoSuite returns the BCCSP provider of sdk. @@ -119,6 +122,11 @@ func (c *Provider) EndpointConfig() fab.EndpointConfig { return c.endpointConfig } +// GetMetrics will return the SDK's metrics instance +func (c *Provider) GetMetrics() *metrics.ClientMetrics { + return c.clientMetrics +} + //SDKContextParams parameter for creating FabContext type SDKContextParams func(opts *Provider) @@ -192,6 +200,13 @@ func WithChannelProvider(channelProvider fab.ChannelProvider) SDKContextParams { } } +//WithClientMetrics sets clientMetrics to Context Provider +func WithClientMetrics(cm *metrics.ClientMetrics) SDKContextParams { + return func(ctx *Provider) { + ctx.clientMetrics = cm + } +} + //NewProvider creates new context client provider // Not be used by end developers, fabsdk package use only func NewProvider(params ...SDKContextParams) *Provider { @@ -258,6 +273,7 @@ func NewChannel(clientProvider context.ClientProvider, channelID string) (*Chann Client: client, channelService: channelService, channelID: channelID, + metrics: client.GetMetrics(), } if pi, ok := channelService.(serviceInit); ok { if err := pi.Initialize(channel); err != nil { diff --git a/pkg/core/config/testdata/config_test.yaml b/pkg/core/config/testdata/config_test.yaml index 711a388c87..3797a28481 100755 --- a/pkg/core/config/testdata/config_test.yaml +++ b/pkg/core/config/testdata/config_test.yaml @@ -390,36 +390,53 @@ certificateAuthorities: ############################################################################### # -# Metrics section -# -# Similar to what's introduced in Fabric 1.3, this section can now -# be used in the SDK (see test/performance for an example showing how this is used) -# Note: In order to use performance metrics, the SDK must be built with 'pprof' build tag +# Operations section +# copied from Fabric's core.yaml ############################################################################### -metrics: - # enable or disable metrics server - enabled: true +operations: + # host and port for the operations server + listenAddress: 127.0.0.1:8080 + + # TLS configuration for the operations endpoint + tls: + # TLS enabled + enabled: false + + # path to PEM encoded server certificate for the operations server + cert: + file: - # when enable metrics server, must specify metrics reporter type - # currently supported type: "statsd","prom" - reporter: prom + # path to PEM encoded server key for the operations server + key: + file: - # determines frequency of report metrics(unit: second) - interval: 1s + # require client certificate authentication to access all resources + clientAuthRequired: false - statsdReporter: + # paths to PEM encoded ca certificates to trust for client authentication + clientRootCAs: + files: [] - # statsd server address to connect - address: peer0.org1.example.com:8125 +############################################################################### +# +# Metrics section +# copied from Fabric's core.yaml +############################################################################### +metrics: + # metrics provider is one of statsd, prometheus, or disabled + provider: prometheus - # determines frequency of push metrics to statsd server(unit: second) - flushInterval: 2s + # statsd configuration + statsd: + # network type: tcp or udp + network: udp - # max size bytes for each push metrics request - # intranet recommend 1432 and internet recommend 512 - flushBytes: 1432 + # statsd server address + address: 127.0.0.1:8125 - promReporter: + # the interval at which locally cached counters and gauges are pushed + # to statsd; timings are pushed immediately + writeInterval: 10s - # prometheus http server listen address for pull metrics - listenAddress: peer0.org1.example.com:8080 + # prefix is prepended to all emitted statsd metrics + prefix: diff --git a/pkg/fab/mocks/mockcontext.go b/pkg/fab/mocks/mockcontext.go index febfabc16c..6e9c6545e1 100644 --- a/pkg/fab/mocks/mockcontext.go +++ b/pkg/fab/mocks/mockcontext.go @@ -16,6 +16,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" "github.com/hyperledger/fabric-sdk-go/pkg/core/mocks" + "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" mspmocks "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp" "strings" @@ -205,6 +206,11 @@ func (pc *MockProviderContext) SetCustomInfraProvider(customInfraProvider fab.In pc.infraProvider = customInfraProvider } +// GetMetrics not used in this mockcontext +func (pc *MockProviderContext) GetMetrics() *metrics.ClientMetrics { + return &metrics.ClientMetrics{} +} + // MockContext holds core providers and identity to enable mocking. type MockContext struct { *MockProviderContext @@ -298,6 +304,11 @@ func (c *MockChannelContext) ChannelID() string { return c.channelID } +// GetMetrics not used in this mockcontext +func (c *MockChannelContext) GetMetrics() *metrics.ClientMetrics { + return &metrics.ClientMetrics{} +} + // MockTransactionHeader supplies a transaction ID and metadata. type MockTransactionHeader struct { MockID fab.TransactionID diff --git a/pkg/fabsdk/fabsdk.go b/pkg/fabsdk/fabsdk.go index 67f63e4d7c..1379714763 100644 --- a/pkg/fabsdk/fabsdk.go +++ b/pkg/fabsdk/fabsdk.go @@ -11,18 +11,21 @@ import ( "math/rand" "time" + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/core/operations" contextApi "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" "github.com/hyperledger/fabric-sdk-go/pkg/context" + "github.com/hyperledger/fabric-sdk-go/pkg/core/config/lookup" "github.com/hyperledger/fabric-sdk-go/pkg/core/logging/api" + "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" "github.com/hyperledger/fabric-sdk-go/pkg/common/logging" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp" - "github.com/hyperledger/fabric-sdk-go/pkg/core/config/lookup" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" fabImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab" sdkApi "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/api" + metricsCfg "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics/cfg" mspImpl "github.com/hyperledger/fabric-sdk-go/pkg/msp" "github.com/pkg/errors" ) @@ -31,15 +34,18 @@ var logger = logging.NewLogger("fabsdk") // FabricSDK provides access (and context) to clients being managed by the SDK. type FabricSDK struct { - opts options - provider *context.Provider - cryptoSuite core.CryptoSuite + opts options + provider *context.Provider + cryptoSuite core.CryptoSuite + system *operations.System + clientMetrics *metrics.ClientMetrics } type configs struct { cryptoSuiteConfig core.CryptoSuiteConfig endpointConfig fab.EndpointConfig identityConfig msp.IdentityConfig + metricsConfig metricsCfg.MetricsConfig } type options struct { @@ -51,6 +57,7 @@ type options struct { endpointConfig fab.EndpointConfig IdentityConfig msp.IdentityConfig ConfigBackend []core.ConfigBackend + metricsConfig metricsCfg.MetricsConfig } // Option configures the SDK. @@ -181,6 +188,20 @@ func WithLoggerPkg(logger api.LoggerProvider) Option { } } +// WithMetricsConfig injects a MetricsConfig interface to the SDK +// it accepts either a full interface of MetricsConfig or a list +// of sub interfaces each implementing one (or more) function(s) of MetricsConfig +func WithMetricsConfig(metricsConfigs ...interface{}) Option { + return func(opts *options) error { + c, err := metricsCfg.BuildConfigMetricsFromOptions(metricsConfigs...) + if err != nil { + return err + } + opts.metricsConfig = c + return nil + } +} + // providerInit interface allows for initializing providers // TODO: minimize interface type providerInit interface { @@ -245,6 +266,8 @@ func initSDK(sdk *FabricSDK, configProvider core.ConfigProvider, opts []Option) return errors.WithMessage(err, "failed to create channel provider") } + sdk.initMetrics(cfg) + //update sdk providers list since all required providers are initialized sdk.provider = context.NewProvider(context.WithCryptoSuiteConfig(cfg.cryptoSuiteConfig), context.WithEndpointConfig(cfg.endpointConfig), @@ -255,7 +278,9 @@ func initSDK(sdk *FabricSDK, configProvider core.ConfigProvider, opts []Option) context.WithLocalDiscoveryProvider(localDiscoveryProvider), context.WithIdentityManagerProvider(identityManagerProvider), context.WithInfraProvider(infraProvider), - context.WithChannelProvider(channelProvider)) + context.WithChannelProvider(channelProvider), + context.WithClientMetrics(sdk.clientMetrics), + ) //initialize if pi, ok := infraProvider.(providerInit); ok { @@ -357,6 +382,7 @@ func (sdk *FabricSDK) loadConfigs(configProvider core.ConfigProvider) (*configs, identityConfig: sdk.opts.IdentityConfig, endpointConfig: sdk.opts.endpointConfig, cryptoSuiteConfig: sdk.opts.CryptoSuiteConfig, + metricsConfig: sdk.opts.metricsConfig, } var configBackend []core.ConfigBackend @@ -391,7 +417,13 @@ func (sdk *FabricSDK) loadConfigs(configProvider core.ConfigProvider) (*configs, // load identity config c.identityConfig, err = sdk.loadIdentityConfig(configBackend...) if err != nil { - return nil, errors.WithMessage(err, "unalbe to load identity config") + return nil, errors.WithMessage(err, "unable to load identity config") + } + + // load metrics config + c.metricsConfig, err = sdk.loadMetricsConfig(configBackend...) + if err != nil { + return nil, errors.WithMessage(err, "unable to load metrics config") } sdk.opts.ConfigBackend = configBackend @@ -467,3 +499,25 @@ func (sdk *FabricSDK) loadIdentityConfig(configBackend ...core.ConfigBackend) (m return identityConfigOpt, nil } + +func (sdk *FabricSDK) loadMetricsConfig(configBackend ...core.ConfigBackend) (metricsCfg.MetricsConfig, error) { + metricsConfigOpt, ok := sdk.opts.metricsConfig.(*metricsCfg.OperationsConfigOptions) + + if sdk.opts.metricsConfig == nil || (ok && !metricsCfg.IsMetricsConfigFullyOverridden(metricsConfigOpt)) { + defMetricsConfig, err := metricsCfg.ConfigFromBackend(configBackend...) + if err != nil { + return nil, errors.WithMessage(err, "failed to initialize metrics config from config backend") + } + if sdk.opts.metricsConfig == nil { + return defMetricsConfig, nil + } + + return metricsCfg.UpdateMissingOptsWithDefaultConfig(metricsConfigOpt, defMetricsConfig), nil + } + + if !ok { + return nil, errors.New("failed to retrieve metrics configs from opts") + } + + return metricsConfigOpt, nil +} diff --git a/pkg/fabsdk/fabsdk_perf.go b/pkg/fabsdk/fabsdk_perf.go new file mode 100644 index 0000000000..dc35421501 --- /dev/null +++ b/pkg/fabsdk/fabsdk_perf.go @@ -0,0 +1,59 @@ +// +build pprof + +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package fabsdk + +import ( + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/core/operations" + flogging "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge" + "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" +) + +// initMetrics will initialize the Go SDK's metric's system instance to allow capturing metrics data by the SDK clients. +func (sdk *FabricSDK) initMetrics(configs *configs) { + if configs == nil { + return + } + if sdk.system == nil { + sdk.system = newOperationsSystem(configs) + + err := sdk.system.Start() + if err != nil { + panic("metrics failed to start: " + err.Error()) + } + + // for now NewClientMetrics supports channel client. TODO: if other client types require metrics tracking, update this function + sdk.clientMetrics = metrics.NewClientMetrics(sdk.system.Provider) + } +} + +func newOperationsSystem(configs *configs) *operations.System { + opsConfig := configs.metricsConfig.OperationCfg() + metricsConfig := configs.metricsConfig.MetricCfg() + return operations.NewSystem(operations.Options{ + Logger: flogging.MustGetLogger("operations.runner"), + ListenAddress: opsConfig.ListenAddress, + Metrics: operations.MetricsOptions{ + Provider: metricsConfig.Provider, + Statsd: &operations.Statsd{ + Network: metricsConfig.Statsd.Network, + Address: metricsConfig.Statsd.Address, + WriteInterval: metricsConfig.Statsd.WriteInterval, + Prefix: metricsConfig.Statsd.Prefix, + }, + }, + TLS: operations.TLS{ + Enabled: opsConfig.TLSEnabled, + CertFile: opsConfig.TLSCertFile, + KeyFile: opsConfig.TLSKeyFile, + ClientCertRequired: opsConfig.ClientAuthRequired, + ClientCACertFiles: opsConfig.ClientRootCAs, + }, + Version: "latest", // TODO expose version somewhere, Fabric uses 'metadata.Version' + }) +} diff --git a/pkg/fabsdk/fabsdk_std.go b/pkg/fabsdk/fabsdk_std.go new file mode 100644 index 0000000000..b6630ce659 --- /dev/null +++ b/pkg/fabsdk/fabsdk_std.go @@ -0,0 +1,28 @@ +// +build !pprof + +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +// Package fabsdk enables client usage of a Hyperledger Fabric network. +package fabsdk + +import ( + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/core/operations" + "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics" +) + +func (sdk *FabricSDK) initMetrics(config *configs) { + //disabled metrics for standard build + sdk.system = operations.NewSystem(operations.Options{ + Metrics: operations.MetricsOptions{ + Provider: "disabled", + }, + Version: "latest", + }, + ) + + sdk.clientMetrics = &metrics.ClientMetrics{} // empty channel ClientMetrics for standard build. +} diff --git a/pkg/fabsdk/metrics/cfg/config.go b/pkg/fabsdk/metrics/cfg/config.go new file mode 100644 index 0000000000..0d258362a6 --- /dev/null +++ b/pkg/fabsdk/metrics/cfg/config.go @@ -0,0 +1,130 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package cfg + +import ( + "time" + + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" + "github.com/hyperledger/fabric-sdk-go/pkg/core/config/lookup" + "github.com/pkg/errors" +) + +// MetricsConfig contains operations system and metrics configuration +type MetricsConfig interface { + OperationCfg() OperationConfig + MetricCfg() MetricConfig +} + +// OperationConfig defines an operations system configuration +type OperationConfig struct { + TLSEnabled bool + ClientAuthRequired bool + ListenAddress string + + // TODO replace TLSCertFile, TLCKeyFile and ClientRootCAs to TLSCACerts (here and in the configs as well) + TLSCertFile string + TLSKeyFile string + ClientRootCAs []string + // END TODO +} + +// MetricConfig defines a metric configuration used along the operation system config +type MetricConfig struct { + // Provider : statsd, prometheus, or disabled + Provider string + // Statsd represents metrics config for Statsd provider + Statsd Statsd +} + +// Statsd config useful for Statsd metrics provider +type Statsd struct { + // Network is statsd network type: tcp or udp + Network string + + // Address is statsd server address: 127.0.0.1:8125 + Address string + + // WriteInterval is the interval at which locally cached counters and gauges are pushed + // to statsd; timings are pushed immediately + WriteInterval time.Duration + + // prefix is prepended to all emitted statsd metrics + Prefix string +} + +// MetricsConfigImpl is the default implementation of MetricsConfig holding config data loaded from backend +type MetricsConfigImpl struct { + backend *lookup.ConfigLookup + OperationConfig + MetricConfig +} + +// OperationCfg returns the oeprations Config +func (m *MetricsConfigImpl) OperationCfg() OperationConfig { + return m.OperationConfig +} + +// MetricCfg returns the metrics Config +func (m *MetricsConfigImpl) MetricCfg() MetricConfig { + return m.MetricConfig +} + +func (m *MetricsConfigImpl) loadMetricsConfiguration() error { + err := m.createOperationCfg() + if err != nil { + return errors.WithMessage(err, "operation system configuration load failed") + } + err = m.createMetricCfg() + if err != nil { + return errors.WithMessage(err, "metric configuration load failed") + } + return nil +} + +func (m *MetricsConfigImpl) createOperationCfg() error { + m.OperationConfig = OperationConfig{ + ListenAddress: m.backend.GetString("operations.listenAddress"), + ClientAuthRequired: m.backend.GetBool("operations.tls.clientAuthRequired"), + TLSCertFile: m.backend.GetString("operations.tls.cert.file"), + TLSKeyFile: m.backend.GetString("operations.tls.key.file"), + TLSEnabled: m.backend.GetBool("operations.tls.enabled"), + } + if rootCAs, ok := m.backend.Lookup("operations.tls.clientRootCAs.files"); ok { + rootCAStrs := make([]string, len(rootCAs.([]interface{}))) + for i, r := range rootCAs.([]interface{}) { + rootCAStrs[i] = r.(string) + } + m.OperationConfig.ClientRootCAs = rootCAStrs + } + + return nil +} + +func (m *MetricsConfigImpl) createMetricCfg() error { + m.MetricConfig = MetricConfig{ + Provider: m.backend.GetString("metrics.provider"), + } + + err := m.backend.UnmarshalKey("metrics.statsd", &m.MetricConfig.Statsd) + if err != nil { + return errors.WithMessage(err, "failed to parse 'metric.statsd' config item to MetricConfig.Statsd type") + } + + return nil +} + +//ConfigFromBackend returns identity config implementation of given backend +func ConfigFromBackend(coreBackend ...core.ConfigBackend) (MetricsConfig, error) { + //create default metrics config + config := &MetricsConfigImpl{backend: lookup.New(coreBackend...)} + //operationsConfig + if err := config.loadMetricsConfiguration(); err != nil { + return nil, errors.WithMessage(err, "metrics configuration load failed") + } + return config, nil +} diff --git a/pkg/fabsdk/metrics/cfg/opts.go b/pkg/fabsdk/metrics/cfg/opts.go new file mode 100644 index 0000000000..8138780636 --- /dev/null +++ b/pkg/fabsdk/metrics/cfg/opts.go @@ -0,0 +1,93 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package cfg + +import "github.com/pkg/errors" + +// OperationsConfigOptions represents MetricsConfig interface with overridable interface functions +// if a function is not overridden, the default MetricsConfig implementation will be used. +type OperationsConfigOptions struct { + operation + metricCfg +} + +type applier func() +type predicate func() bool +type setter struct{ isSet bool } + +// operation interface allows to uniquely override MetricsConfig interface's OperationConfig() function +type operation interface { + OperationCfg() OperationConfig +} + +// caConfig interface allows to uniquely override MetricsConfig interface's CAConfig() function +type metricCfg interface { + MetricCfg() MetricConfig +} + +// BuildConfigMetricsFromOptions will return a MetricsConfig instance pre-built with Optional interfaces +// provided in fabsdk's WithMetricsConfig(opts...) call +func BuildConfigMetricsFromOptions(opts ...interface{}) (MetricsConfig, error) { + // build a new MetricsConfig with overridden function implementations + c := &OperationsConfigOptions{} + for _, option := range opts { + err := setMetricsConfigWithOptionInterface(c, option) + if err != nil { + return nil, err + } + } + + return c, nil +} + +// UpdateMissingOptsWithDefaultConfig will verify if any functions of the MetricsConfig were not updated with fabsdk's +// WithConfigMetrics(opts...) call, then use default MetricsConfig interface for these functions instead +func UpdateMissingOptsWithDefaultConfig(c *OperationsConfigOptions, d MetricsConfig) MetricsConfig { + s := &setter{} + + s.set(c.operation, nil, func() { c.operation = d }) + s.set(c.metricCfg, nil, func() { c.metricCfg = d }) + + return c +} + +// IsMetricsConfigFullyOverridden will return true if all of the argument's sub interfaces is not nil +// (ie MetricsConfig interface not fully overridden) +func IsMetricsConfigFullyOverridden(c *OperationsConfigOptions) bool { + return !anyNil(c.operation, c.metricCfg) +} + +// will override MetricsConfig interface with functions provided by o (option) +func setMetricsConfigWithOptionInterface(c *OperationsConfigOptions, o interface{}) error { + s := &setter{} + + s.set(c.operation, func() bool { _, ok := o.(operation); return ok }, func() { c.operation = o.(operation) }) + s.set(c.metricCfg, func() bool { _, ok := o.(metricCfg); return ok }, func() { c.metricCfg = o.(metricCfg) }) + + if !s.isSet { + return errors.Errorf("option %#v is not a sub interface of MetricsConfig, at least one of its functions must be implemented.", o) + } + return nil +} + +// needed to avoid meta-linter errors (too many if conditions) +func (o *setter) set(current interface{}, check predicate, apply applier) { + if current == nil && (check == nil || check()) { + apply() + o.isSet = true + } +} + +// will verify if any of objs element is nil, also needed to avoid meta-linter errors +func anyNil(objs ...interface{}) bool { + for _, p := range objs { + if p == nil { + return true + } + } + return false +} diff --git a/pkg/fabsdk/metrics/cfg/opts_test.go b/pkg/fabsdk/metrics/cfg/opts_test.go new file mode 100644 index 0000000000..2c2f1959f3 --- /dev/null +++ b/pkg/fabsdk/metrics/cfg/opts_test.go @@ -0,0 +1,127 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package cfg + +import ( + "testing" + "time" +) + +var ( + m0 = &MetricsConfigImpl{} + m1 = &mockOperationConfig{} + m2 = &mockMetricConfig{} +) + +func TestCreateCustomFullMetricsConfig(t *testing.T) { + var opts []interface{} + opts = append(opts, m0) + // try to build with the overall interface (m0 is the overall interface implementation) + metricConfigOption, err := BuildConfigMetricsFromOptions(opts...) + if err != nil { + t.Fatalf("BuildConfigMetricsFromOptions returned unexpected error %s", err) + } + if metricConfigOption == nil { + t.Fatal("BuildConfigMetricsFromOptions call returned nil") + } +} + +func TestCreateCustomMetricConfig(t *testing.T) { + // try to build with separate interfaces + metricsConfigOption, err := BuildConfigMetricsFromOptions(m1, m2) + if err != nil { + t.Fatalf("BuildConfigMetricsFromOptions returned unexpected error %s", err) + } + var oco *OperationsConfigOptions + var ok bool + if oco, ok = metricsConfigOption.(*OperationsConfigOptions); !ok { + t.Fatalf("BuildConfigMetricsFromOptions did not return a Options instance %T", metricsConfigOption) + } + if oco == nil { + t.Fatal("build OperationsConfigOptions returned is nil") + } + + metCfg := oco.MetricCfg() + if &metCfg == nil { + t.Fatalf("MetricsConfig was supposed to have MetricCfg function overridden from Options but was not %+v. MetricCfg: %s", oco, metCfg) + } + + opCfg := oco.OperationCfg() + if &opCfg == nil { + t.Fatalf("MetricsConfig was supposed to have OperationCfg function overridden from Options but was not %+v. OperationCfg: %s", oco, metCfg) + } + +} + +func TestIsMetricsConfigFullyOverridden(t *testing.T) { + // test with the some interfaces + metricsConfigOption, err := BuildConfigMetricsFromOptions(m1) + if err != nil { + t.Fatalf("BuildConfigMetricsFromOptions returned unexpected error %s", err) + } + + var oco *OperationsConfigOptions + var ok bool + if oco, ok = metricsConfigOption.(*OperationsConfigOptions); !ok { + t.Fatalf("BuildConfigMetricsFromOptions did not return a Options instance %T", metricsConfigOption) + } + + // test verify if some interfaces were not overridden according to BuildConfigEndpointFromOptions above, + // only 1 interface was overridden, so expected value is false + isFullyOverridden := IsMetricsConfigFullyOverridden(oco) + if isFullyOverridden { + t.Fatal("Expected not fully overridden MetricsConfig interface, but received fully overridden.") + } + + // now try with no opts, expected value is also false + metricsConfigOption, err = BuildConfigMetricsFromOptions() + if err != nil { + t.Fatalf("BuildConfigMetricsFromOptions returned unexpected error %s", err) + } + if oco, ok = metricsConfigOption.(*OperationsConfigOptions); !ok { + t.Fatalf("BuildConfigMetricsFromOptions did not return a Options instance %T", metricsConfigOption) + } + + isFullyOverridden = IsMetricsConfigFullyOverridden(oco) + if isFullyOverridden { + t.Fatal("Expected not fully overridden MetricsConfig interface with empty options, but received fully overridden.") + } + + // now try with all opts, expected value is true this time + metricsConfigOption, err = BuildConfigMetricsFromOptions(m1, m2) + if err != nil { + t.Fatalf("BuildConfigMetricsFromOptions returned unexpected error %s", err) + } + if oco, ok = metricsConfigOption.(*OperationsConfigOptions); !ok { + t.Fatalf("BuildConfigMetricsFromOptions did not return a Options instance %T", metricsConfigOption) + } + + isFullyOverridden = IsMetricsConfigFullyOverridden(oco) + if !isFullyOverridden { + t.Fatal("Expected fully overridden MetricsConfig interface, but received not fully overridden.") + } +} + +type mockOperationConfig struct{} + +func (m *mockOperationConfig) OperationCfg() OperationConfig { + return OperationConfig{} +} + +type mockMetricConfig struct{} + +func (m *mockMetricConfig) MetricCfg() MetricConfig { + return MetricConfig{ + Provider: "disabled", + Statsd: Statsd{ + Prefix: "test", + WriteInterval: 2 * time.Second, + Address: "127.0.0.1:8080", + Network: "udp", + }, + } +} diff --git a/pkg/fabsdk/metrics/metrics.go b/pkg/fabsdk/metrics/metrics.go new file mode 100644 index 0000000000..3e8705694c --- /dev/null +++ b/pkg/fabsdk/metrics/metrics.go @@ -0,0 +1,95 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package metrics + +import "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" + +var ( + // for now, only channel clients require metrics tracking. TODO: update to generalize metrics for other client types if needed. + queriesReceived = metrics.CounterOpts{ + Namespace: "channel", + Name: "queries_received", + Help: "The number of channel client queries received.", + LabelNames: []string{"chaincode", "Fcn"}, + StatsdFormat: "%{#fqname}.%{type}.%{channel}.%{query}", + } + queriesFailed = metrics.CounterOpts{ + Namespace: "channel", + Name: "queries_failed", + Help: "The number of channel client queries that failed (timeouts excluded).", + LabelNames: []string{"chaincode", "Fcn", "fail"}, + StatsdFormat: "%{#fqname}.%{type}.%{channel}.%{query}.%{fail}", + } + queryTimeouts = metrics.CounterOpts{ + Namespace: "channel", + Name: "query_timeouts", + Help: "The number of channel queries that have failed due to time out.", + LabelNames: []string{"chaincode", "Fcn", "fail"}, + StatsdFormat: "%{#fqname}.%{type}.%{channel}.%{query}.%{timeout}", + } + queryDuration = metrics.HistogramOpts{ + Namespace: "channel", + Name: "query_duration", + Help: "The time to complete channel client query.", + LabelNames: []string{"chaincode", "Fcn"}, + StatsdFormat: "%{#fqname}.%{type}.%{channel}.%{query}", + } + executionsReceived = metrics.CounterOpts{ + Namespace: "channel", + Name: "executions_received", + Help: "The number of channel client executions received.", + LabelNames: []string{"chaincode", "Fcn"}, + StatsdFormat: "%{#fqname}.%{type}.%{channel}.%{execute}", + } + executionsFailed = metrics.CounterOpts{ + Namespace: "channel", + Name: "executions_failed", + Help: "The number of channel client executions that failed (timeouts excluded).", + LabelNames: []string{"chaincode", "Fcn", "fail"}, + StatsdFormat: "%{#fqname}.%{type}.%{channel}.%{execute}.%{fail}", + } + executionTimeouts = metrics.CounterOpts{ + Namespace: "channel", + Name: "execution_timeouts", + Help: "The number of channel executions that have failed due to time out.", + LabelNames: []string{"chaincode", "Fcn", "fail"}, + StatsdFormat: "%{#fqname}.%{type}.%{channel}.%{execute}.%{timeout}", + } + executionDuration = metrics.HistogramOpts{ + Namespace: "channel", + Name: "execution_duration", + Help: "The time to complete channel client execution.", + LabelNames: []string{"chaincode", "Fcn"}, + StatsdFormat: "%{#fqname}.%{type}.%{channel}.%{execution}", + } +) + +// ClientMetrics contains the metrics used in the (channel) client +type ClientMetrics struct { + QueriesReceived metrics.Counter + QueriesFailed metrics.Counter + QueryDuration metrics.Histogram + QueryTimeouts metrics.Counter + ExecutionsReceived metrics.Counter + ExecutionsFailed metrics.Counter + ExecutionDuration metrics.Histogram + ExecutionTimeouts metrics.Counter +} + +// NewClientMetrics builds a new instance of ClientMetrics +func NewClientMetrics(p metrics.Provider) *ClientMetrics { + return &ClientMetrics{ + QueriesReceived: p.NewCounter(queriesReceived), + QueriesFailed: p.NewCounter(queriesFailed), + QueryDuration: p.NewHistogram(queryDuration), + QueryTimeouts: p.NewCounter(queryTimeouts), + ExecutionsReceived: p.NewCounter(executionsReceived), + ExecutionsFailed: p.NewCounter(executionsFailed), + ExecutionDuration: p.NewHistogram(executionDuration), + ExecutionTimeouts: p.NewCounter(executionTimeouts), + } +} diff --git a/pkg/fabsdk/test/mocksdkapi/mocksdkapi.gen.go b/pkg/fabsdk/test/mocksdkapi/mocksdkapi.gen.go index 12033e9b3d..d9ecbaf27a 100644 --- a/pkg/fabsdk/test/mocksdkapi/mocksdkapi.gen.go +++ b/pkg/fabsdk/test/mocksdkapi/mocksdkapi.gen.go @@ -38,6 +38,7 @@ func (m *MockCoreProviderFactory) EXPECT() *MockCoreProviderFactoryMockRecorder // CreateCryptoSuiteProvider mocks base method func (m *MockCoreProviderFactory) CreateCryptoSuiteProvider(arg0 core.CryptoSuiteConfig) (core.CryptoSuite, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateCryptoSuiteProvider", arg0) ret0, _ := ret[0].(core.CryptoSuite) ret1, _ := ret[1].(error) @@ -46,11 +47,13 @@ func (m *MockCoreProviderFactory) CreateCryptoSuiteProvider(arg0 core.CryptoSuit // CreateCryptoSuiteProvider indicates an expected call of CreateCryptoSuiteProvider func (mr *MockCoreProviderFactoryMockRecorder) CreateCryptoSuiteProvider(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCryptoSuiteProvider", reflect.TypeOf((*MockCoreProviderFactory)(nil).CreateCryptoSuiteProvider), arg0) } // CreateInfraProvider mocks base method func (m *MockCoreProviderFactory) CreateInfraProvider(arg0 fab.EndpointConfig) (fab.InfraProvider, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateInfraProvider", arg0) ret0, _ := ret[0].(fab.InfraProvider) ret1, _ := ret[1].(error) @@ -59,11 +62,13 @@ func (m *MockCoreProviderFactory) CreateInfraProvider(arg0 fab.EndpointConfig) ( // CreateInfraProvider indicates an expected call of CreateInfraProvider func (mr *MockCoreProviderFactoryMockRecorder) CreateInfraProvider(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateInfraProvider", reflect.TypeOf((*MockCoreProviderFactory)(nil).CreateInfraProvider), arg0) } // CreateSigningManager mocks base method func (m *MockCoreProviderFactory) CreateSigningManager(arg0 core.CryptoSuite) (core.SigningManager, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateSigningManager", arg0) ret0, _ := ret[0].(core.SigningManager) ret1, _ := ret[1].(error) @@ -72,6 +77,7 @@ func (m *MockCoreProviderFactory) CreateSigningManager(arg0 core.CryptoSuite) (c // CreateSigningManager indicates an expected call of CreateSigningManager func (mr *MockCoreProviderFactoryMockRecorder) CreateSigningManager(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSigningManager", reflect.TypeOf((*MockCoreProviderFactory)(nil).CreateSigningManager), arg0) } @@ -100,6 +106,7 @@ func (m *MockMSPProviderFactory) EXPECT() *MockMSPProviderFactoryMockRecorder { // CreateIdentityManagerProvider mocks base method func (m *MockMSPProviderFactory) CreateIdentityManagerProvider(arg0 fab.EndpointConfig, arg1 core.CryptoSuite, arg2 msp.UserStore) (msp.IdentityManagerProvider, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateIdentityManagerProvider", arg0, arg1, arg2) ret0, _ := ret[0].(msp.IdentityManagerProvider) ret1, _ := ret[1].(error) @@ -108,11 +115,13 @@ func (m *MockMSPProviderFactory) CreateIdentityManagerProvider(arg0 fab.Endpoint // CreateIdentityManagerProvider indicates an expected call of CreateIdentityManagerProvider func (mr *MockMSPProviderFactoryMockRecorder) CreateIdentityManagerProvider(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateIdentityManagerProvider", reflect.TypeOf((*MockMSPProviderFactory)(nil).CreateIdentityManagerProvider), arg0, arg1, arg2) } // CreateUserStore mocks base method func (m *MockMSPProviderFactory) CreateUserStore(arg0 msp.IdentityConfig) (msp.UserStore, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateUserStore", arg0) ret0, _ := ret[0].(msp.UserStore) ret1, _ := ret[1].(error) @@ -121,6 +130,7 @@ func (m *MockMSPProviderFactory) CreateUserStore(arg0 msp.IdentityConfig) (msp.U // CreateUserStore indicates an expected call of CreateUserStore func (mr *MockMSPProviderFactoryMockRecorder) CreateUserStore(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUserStore", reflect.TypeOf((*MockMSPProviderFactory)(nil).CreateUserStore), arg0) } @@ -149,6 +159,7 @@ func (m *MockServiceProviderFactory) EXPECT() *MockServiceProviderFactoryMockRec // CreateChannelProvider mocks base method func (m *MockServiceProviderFactory) CreateChannelProvider(arg0 fab.EndpointConfig) (fab.ChannelProvider, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateChannelProvider", arg0) ret0, _ := ret[0].(fab.ChannelProvider) ret1, _ := ret[1].(error) @@ -157,11 +168,13 @@ func (m *MockServiceProviderFactory) CreateChannelProvider(arg0 fab.EndpointConf // CreateChannelProvider indicates an expected call of CreateChannelProvider func (mr *MockServiceProviderFactoryMockRecorder) CreateChannelProvider(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateChannelProvider", reflect.TypeOf((*MockServiceProviderFactory)(nil).CreateChannelProvider), arg0) } // CreateLocalDiscoveryProvider mocks base method func (m *MockServiceProviderFactory) CreateLocalDiscoveryProvider(arg0 fab.EndpointConfig) (fab.LocalDiscoveryProvider, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateLocalDiscoveryProvider", arg0) ret0, _ := ret[0].(fab.LocalDiscoveryProvider) ret1, _ := ret[1].(error) @@ -170,5 +183,6 @@ func (m *MockServiceProviderFactory) CreateLocalDiscoveryProvider(arg0 fab.Endpo // CreateLocalDiscoveryProvider indicates an expected call of CreateLocalDiscoveryProvider func (mr *MockServiceProviderFactoryMockRecorder) CreateLocalDiscoveryProvider(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateLocalDiscoveryProvider", reflect.TypeOf((*MockServiceProviderFactory)(nil).CreateLocalDiscoveryProvider), arg0) } diff --git a/pkg/msp/enrollment_test.go b/pkg/msp/enrollment_test.go index 4614c4fca5..0628d61ca7 100644 --- a/pkg/msp/enrollment_test.go +++ b/pkg/msp/enrollment_test.go @@ -20,6 +20,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite" "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/sw" "github.com/hyperledger/fabric-sdk-go/pkg/fab" + "github.com/hyperledger/fabric-sdk-go/pkg/msp/api" apimocks "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmspapi" ) @@ -121,7 +122,7 @@ func checkSigningIdentityWithEnrollment(cryptoConfig core.CryptoSuiteConfig, t * defer ctrl.Finish() caClient := apimocks.NewMockCAClient(ctrl) prepareForEnroll(t, caClient, cs) - err = caClient.Enroll(userToEnroll, "enrollmentSecret") + err = caClient.Enroll(&api.EnrollmentRequest{Name: userToEnroll, Secret: "enrollmentSecret"}) if err != nil { t.Fatalf("fabricCAClient Enroll failed: %s", err) } @@ -137,7 +138,7 @@ func prepareForEnroll(t *testing.T, mc *apimocks.MockCAClient, cs core.CryptoSui var err error - mc.EXPECT().Enroll(gomock.Any(), gomock.Any()).Do(func(enrollmentID string, enrollmentSecret string) { + mc.EXPECT().Enroll(gomock.Any()).Do(func(enrollmentRequest *api.EnrollmentRequest) { // Simulate key and cert management normally done by the SDK diff --git a/pkg/msp/test/mockmspapi/mockmspapi.gen.go b/pkg/msp/test/mockmspapi/mockmspapi.gen.go index 43785e2be8..076dbb11be 100644 --- a/pkg/msp/test/mockmspapi/mockmspapi.gen.go +++ b/pkg/msp/test/mockmspapi/mockmspapi.gen.go @@ -34,8 +34,24 @@ func (m *MockCAClient) EXPECT() *MockCAClientMockRecorder { return m.recorder } +// AddAffiliation mocks base method +func (m *MockCAClient) AddAffiliation(arg0 *api.AffiliationRequest) (*api.AffiliationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddAffiliation", arg0) + ret0, _ := ret[0].(*api.AffiliationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AddAffiliation indicates an expected call of AddAffiliation +func (mr *MockCAClientMockRecorder) AddAffiliation(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAffiliation", reflect.TypeOf((*MockCAClient)(nil).AddAffiliation), arg0) +} + // CreateIdentity mocks base method func (m *MockCAClient) CreateIdentity(arg0 *api.IdentityRequest) (*api.IdentityResponse, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateIdentity", arg0) ret0, _ := ret[0].(*api.IdentityResponse) ret1, _ := ret[1].(error) @@ -44,23 +60,57 @@ func (m *MockCAClient) CreateIdentity(arg0 *api.IdentityRequest) (*api.IdentityR // CreateIdentity indicates an expected call of CreateIdentity func (mr *MockCAClientMockRecorder) CreateIdentity(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateIdentity", reflect.TypeOf((*MockCAClient)(nil).CreateIdentity), arg0) } // Enroll mocks base method -func (m *MockCAClient) Enroll(arg0, arg1 string) error { - ret := m.ctrl.Call(m, "Enroll", arg0, arg1) +func (m *MockCAClient) Enroll(arg0 *api.EnrollmentRequest) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Enroll", arg0) ret0, _ := ret[0].(error) return ret0 } // Enroll indicates an expected call of Enroll -func (mr *MockCAClientMockRecorder) Enroll(arg0, arg1 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Enroll", reflect.TypeOf((*MockCAClient)(nil).Enroll), arg0, arg1) +func (mr *MockCAClientMockRecorder) Enroll(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Enroll", reflect.TypeOf((*MockCAClient)(nil).Enroll), arg0) +} + +// GetAffiliation mocks base method +func (m *MockCAClient) GetAffiliation(arg0, arg1 string) (*api.AffiliationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAffiliation", arg0, arg1) + ret0, _ := ret[0].(*api.AffiliationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAffiliation indicates an expected call of GetAffiliation +func (mr *MockCAClientMockRecorder) GetAffiliation(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAffiliation", reflect.TypeOf((*MockCAClient)(nil).GetAffiliation), arg0, arg1) +} + +// GetAllAffiliations mocks base method +func (m *MockCAClient) GetAllAffiliations(arg0 string) (*api.AffiliationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllAffiliations", arg0) + ret0, _ := ret[0].(*api.AffiliationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAllAffiliations indicates an expected call of GetAllAffiliations +func (mr *MockCAClientMockRecorder) GetAllAffiliations(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllAffiliations", reflect.TypeOf((*MockCAClient)(nil).GetAllAffiliations), arg0) } // GetAllIdentities mocks base method func (m *MockCAClient) GetAllIdentities(arg0 string) ([]*api.IdentityResponse, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetAllIdentities", arg0) ret0, _ := ret[0].([]*api.IdentityResponse) ret1, _ := ret[1].(error) @@ -69,11 +119,28 @@ func (m *MockCAClient) GetAllIdentities(arg0 string) ([]*api.IdentityResponse, e // GetAllIdentities indicates an expected call of GetAllIdentities func (mr *MockCAClientMockRecorder) GetAllIdentities(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllIdentities", reflect.TypeOf((*MockCAClient)(nil).GetAllIdentities), arg0) } +// GetCAInfo mocks base method +func (m *MockCAClient) GetCAInfo() (*api.GetCAInfoResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCAInfo") + ret0, _ := ret[0].(*api.GetCAInfoResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCAInfo indicates an expected call of GetCAInfo +func (mr *MockCAClientMockRecorder) GetCAInfo() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCAInfo", reflect.TypeOf((*MockCAClient)(nil).GetCAInfo)) +} + // GetIdentity mocks base method func (m *MockCAClient) GetIdentity(arg0, arg1 string) (*api.IdentityResponse, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetIdentity", arg0, arg1) ret0, _ := ret[0].(*api.IdentityResponse) ret1, _ := ret[1].(error) @@ -82,11 +149,28 @@ func (m *MockCAClient) GetIdentity(arg0, arg1 string) (*api.IdentityResponse, er // GetIdentity indicates an expected call of GetIdentity func (mr *MockCAClientMockRecorder) GetIdentity(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIdentity", reflect.TypeOf((*MockCAClient)(nil).GetIdentity), arg0, arg1) } +// ModifyAffiliation mocks base method +func (m *MockCAClient) ModifyAffiliation(arg0 *api.ModifyAffiliationRequest) (*api.AffiliationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ModifyAffiliation", arg0) + ret0, _ := ret[0].(*api.AffiliationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ModifyAffiliation indicates an expected call of ModifyAffiliation +func (mr *MockCAClientMockRecorder) ModifyAffiliation(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyAffiliation", reflect.TypeOf((*MockCAClient)(nil).ModifyAffiliation), arg0) +} + // ModifyIdentity mocks base method func (m *MockCAClient) ModifyIdentity(arg0 *api.IdentityRequest) (*api.IdentityResponse, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ModifyIdentity", arg0) ret0, _ := ret[0].(*api.IdentityResponse) ret1, _ := ret[1].(error) @@ -95,11 +179,13 @@ func (m *MockCAClient) ModifyIdentity(arg0 *api.IdentityRequest) (*api.IdentityR // ModifyIdentity indicates an expected call of ModifyIdentity func (mr *MockCAClientMockRecorder) ModifyIdentity(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyIdentity", reflect.TypeOf((*MockCAClient)(nil).ModifyIdentity), arg0) } // Reenroll mocks base method -func (m *MockCAClient) Reenroll(arg0 string) error { +func (m *MockCAClient) Reenroll(arg0 *api.ReenrollmentRequest) error { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Reenroll", arg0) ret0, _ := ret[0].(error) return ret0 @@ -107,11 +193,13 @@ func (m *MockCAClient) Reenroll(arg0 string) error { // Reenroll indicates an expected call of Reenroll func (mr *MockCAClientMockRecorder) Reenroll(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reenroll", reflect.TypeOf((*MockCAClient)(nil).Reenroll), arg0) } // Register mocks base method func (m *MockCAClient) Register(arg0 *api.RegistrationRequest) (string, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Register", arg0) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) @@ -120,11 +208,28 @@ func (m *MockCAClient) Register(arg0 *api.RegistrationRequest) (string, error) { // Register indicates an expected call of Register func (mr *MockCAClientMockRecorder) Register(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockCAClient)(nil).Register), arg0) } +// RemoveAffiliation mocks base method +func (m *MockCAClient) RemoveAffiliation(arg0 *api.AffiliationRequest) (*api.AffiliationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveAffiliation", arg0) + ret0, _ := ret[0].(*api.AffiliationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RemoveAffiliation indicates an expected call of RemoveAffiliation +func (mr *MockCAClientMockRecorder) RemoveAffiliation(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveAffiliation", reflect.TypeOf((*MockCAClient)(nil).RemoveAffiliation), arg0) +} + // RemoveIdentity mocks base method func (m *MockCAClient) RemoveIdentity(arg0 *api.RemoveIdentityRequest) (*api.IdentityResponse, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoveIdentity", arg0) ret0, _ := ret[0].(*api.IdentityResponse) ret1, _ := ret[1].(error) @@ -133,11 +238,13 @@ func (m *MockCAClient) RemoveIdentity(arg0 *api.RemoveIdentityRequest) (*api.Ide // RemoveIdentity indicates an expected call of RemoveIdentity func (mr *MockCAClientMockRecorder) RemoveIdentity(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveIdentity", reflect.TypeOf((*MockCAClient)(nil).RemoveIdentity), arg0) } // Revoke mocks base method func (m *MockCAClient) Revoke(arg0 *api.RevocationRequest) (*api.RevocationResponse, error) { + m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Revoke", arg0) ret0, _ := ret[0].(*api.RevocationResponse) ret1, _ := ret[1].(error) @@ -146,5 +253,6 @@ func (m *MockCAClient) Revoke(arg0 *api.RevocationRequest) (*api.RevocationRespo // Revoke indicates an expected call of Revoke func (mr *MockCAClientMockRecorder) Revoke(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Revoke", reflect.TypeOf((*MockCAClient)(nil).Revoke), arg0) } diff --git a/scripts/_go/src/gofilter/cmd/gofilter/gofilter.go b/scripts/_go/src/gofilter/cmd/gofilter/gofilter.go index e35eabbc72..3a79edd964 100644 --- a/scripts/_go/src/gofilter/cmd/gofilter/gofilter.go +++ b/scripts/_go/src/gofilter/cmd/gofilter/gofilter.go @@ -87,7 +87,7 @@ func main() { fileset := token.NewFileSet() astFile, err := parser.ParseFile(fileset, *filename, nil, parser.ParseComments) if err != nil { - fmt.Fprintf(os.Stderr, "Error paring file: %s\n", err) + fmt.Fprintf(os.Stderr, "Error parsing file: %s\n", err) os.Exit(1) } diff --git a/scripts/third_party_pins/fabric/apply_fabric_client_utils.sh b/scripts/third_party_pins/fabric/apply_fabric_client_utils.sh index 7ca4bb07f5..77773bfd46 100755 --- a/scripts/third_party_pins/fabric/apply_fabric_client_utils.sh +++ b/scripts/third_party_pins/fabric/apply_fabric_client_utils.sh @@ -34,8 +34,18 @@ declare -a PKGS=( "common/attrmgr" "common/ledger" "common/metrics" + "common/metrics/disabled" + "common/metrics/internal/namer" + "common/metrics/prometheus" + "common/metrics/statsd" + "common/metrics/statsd/goruntime" + + "core/comm" + "core/middleware" + "core/operations" "sdkpatch/logbridge" + "sdkpatch/logbridge/httpadmin" "sdkpatch/cryptosuitebridge" "sdkpatch/cachebridge" @@ -95,10 +105,12 @@ declare -a FILES=( "bccsp/utils/slice.go" "bccsp/utils/x509.go" "bccsp/utils/ecdsa.go" + + "core/comm/config.go" + "common/crypto/random.go" "common/crypto/signer.go" - "common/util/utils.go" "common/attrmgr/attrmgr.go" "common/channelconfig/applicationorg.go" @@ -110,9 +122,25 @@ declare -a FILES=( "common/ledger/ledger_interface.go" + "common/metrics/disabled/provider.go" + "common/metrics/internal/namer/namer.go" + "common/metrics/prometheus/provider.go" "common/metrics/provider.go" + "common/metrics/statsd/goruntime/collector.go" + "common/metrics/statsd/goruntime/metrics.go" + "common/metrics/statsd/provider.go" + + "core/middleware/chain.go" + "core/middleware/request_id.go" + "core/middleware/require_cert.go" + "core/operations/metrics.go" + "core/operations/system.go" + "core/operations/tls.go" + + "common/util/utils.go" "sdkpatch/logbridge/logbridge.go" + "sdkpatch/logbridge/httpadmin/spec.go" "sdkpatch/cryptosuitebridge/cryptosuitebridge.go" "sdkpatch/cachebridge/cache.go" @@ -254,9 +282,16 @@ FILTER_FN= gofilter FILTER_FILENAME="common/util/utils.go" -FILTER_FN="CreateUtcTimestamp,ConcatenateBytes" +FILTER_FN="CreateUtcTimestamp,ConcatenateBytes,GenerateBytesUUID,GenerateIntUUID,GenerateUUID,idBytesToStr" gofilter +FILTER_FILENAME="core/comm/config.go" +sed -i'' -e 's/flogging\.FabricLogger/flogging.Logger/g' "${TMP_PROJECT_PATH}/${FILTER_FILENAME}" +sed -i'' -e '/MetricsProvider metrics\.Provider/ a\ +\/\/ HealthCheckEnabled enables the gRPC Health Checking Protocol for the server\ + HealthCheckEnabled bool\ +' "${TMP_PROJECT_PATH}/${FILTER_FILENAME}" + FILTER_FILENAME="common/channelconfig/applicationorg.go" FILTER_FN= gofilter diff --git a/scripts/third_party_pins/fabric/apply_upstream.sh b/scripts/third_party_pins/fabric/apply_upstream.sh index 571de3718b..b9c465882c 100755 --- a/scripts/third_party_pins/fabric/apply_upstream.sh +++ b/scripts/third_party_pins/fabric/apply_upstream.sh @@ -51,6 +51,7 @@ mkdir -p "${THIRDPARTY_FABRIC_PATH}/protos" echo "Pinning and patching fabric client utils..." declare -a CLIENT_UTILS_IMPORT_SUBSTS=( 's/[[:space:]]logging[[:space:]]\"github.com/\"github.com/g' + 's/\"github.com\/hyperledger\/fabric\/common\/flogging\/httpadmin/\"github.com\/hyperledger\/fabric-sdk-go\/internal\/github.com\/hyperledger\/fabric\/sdkpatch\/logbridge\/httpadmin/g' 's/\"github.com\/hyperledger\/fabric\/common\/flogging/flogging\"github.com\/hyperledger\/fabric-sdk-go\/internal\/github.com\/hyperledger\/fabric\/sdkpatch\/logbridge/g' 's/\"github.com\/op\/go-logging/logging\"github.com\/hyperledger\/fabric-sdk-go\/internal\/github.com\/hyperledger\/fabric\/sdkpatch\/logbridge/g' 's/\"github.com\/hyperledger\/fabric\/bccsp/\"github.com\/hyperledger\/fabric-sdk-go\/internal\/github.com\/hyperledger\/fabric\/bccsp/g' diff --git a/scripts/third_party_pins/fabric/patches/0005-logbridge-httpadmin.patch b/scripts/third_party_pins/fabric/patches/0005-logbridge-httpadmin.patch new file mode 100644 index 0000000000..faa598d932 --- /dev/null +++ b/scripts/third_party_pins/fabric/patches/0005-logbridge-httpadmin.patch @@ -0,0 +1,101 @@ +From 3aad7a7d25b512bf922b5db87a400e453c6bb9af Mon Sep 17 00:00:00 2001 +From: Baha Shaaban +Date: Mon, 14 Jan 2019 11:27:13 -0500 +Subject: [PATCH] logbridge httpadmin + +Signed-off-by: Baha Shaaban +--- + sdkpatch/logbridge/httpadmin/spec.go | 81 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 81 insertions(+) + create mode 100644 sdkpatch/logbridge/httpadmin/spec.go + +diff --git a/sdkpatch/logbridge/httpadmin/spec.go b/sdkpatch/logbridge/httpadmin/spec.go +new file mode 100644 +index 000000000..deac6e33d +--- /dev/null ++++ b/sdkpatch/logbridge/httpadmin/spec.go +@@ -0,0 +1,81 @@ ++/* ++Copyright IBM Corp. All Rights Reserved. ++ ++SPDX-License-Identifier: Apache-2.0 ++*/ ++ ++package httpadmin ++ ++import ( ++ "encoding/json" ++ "fmt" ++ "net/http" ++ ++ flogging "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge" ++) ++ ++//go:generate counterfeiter -o fakes/logging.go -fake-name Logging . Logging ++ ++type Logging interface { ++ ActivateSpec(spec string) error ++ Spec() string ++} ++ ++type LogSpec struct { ++ Spec string `json:"spec,omitempty"` ++} ++ ++type ErrorResponse struct { ++ Error string `json:"error"` ++} ++ ++func NewSpecHandler() *SpecHandler { ++ return &SpecHandler{ ++ Logger: flogging.MustGetLogger("flogging.httpadmin"), ++ } ++} ++ ++type SpecHandler struct { ++ Logging Logging ++ Logger *flogging.Logger ++} ++ ++func (h *SpecHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ++ switch req.Method { ++ case http.MethodPut: ++ var logSpec LogSpec ++ decoder := json.NewDecoder(req.Body) ++ if err := decoder.Decode(&logSpec); err != nil { ++ h.sendResponse(resp, http.StatusBadRequest, err) ++ return ++ } ++ req.Body.Close() ++ ++ if err := h.Logging.ActivateSpec(logSpec.Spec); err != nil { ++ h.sendResponse(resp, http.StatusBadRequest, err) ++ return ++ } ++ resp.WriteHeader(http.StatusNoContent) ++ ++ case http.MethodGet: ++ h.sendResponse(resp, http.StatusOK, &LogSpec{Spec: h.Logging.Spec()}) ++ ++ default: ++ err := fmt.Errorf("invalid request method: %s", req.Method) ++ h.sendResponse(resp, http.StatusBadRequest, err) ++ } ++} ++ ++func (h *SpecHandler) sendResponse(resp http.ResponseWriter, code int, payload interface{}) { ++ encoder := json.NewEncoder(resp) ++ if err, ok := payload.(error); ok { ++ payload = &ErrorResponse{Error: err.Error()} ++ } ++ ++ resp.WriteHeader(code) ++ ++ resp.Header().Set("Content-Type", "application/json") ++ if err := encoder.Encode(payload); err != nil { ++ h.Logger.Errorf("[error] failed to encode payload", err) ++ } ++} +-- +2.15.0 + diff --git a/test/fixtures/config/config_test.yaml b/test/fixtures/config/config_test.yaml index 7d1790c6a1..91d1214ff9 100644 --- a/test/fixtures/config/config_test.yaml +++ b/test/fixtures/config/config_test.yaml @@ -534,3 +534,57 @@ certificateAuthorities: # urlSubstitutionExp: # sslTargetOverrideUrlSubstitutionExp: ca.example.com # mappedHost: ca.org2.example.com + +############################################################################### +# +# Operations section +# copied from Fabric's core.yaml +############################################################################### +operations: + # host and port for the operations server + listenAddress: 127.0.0.1:8080 + + # TLS configuration for the operations endpoint + tls: + # TLS enabled + enabled: false + + # TODO replace cert.file, key.file and clientRootCAs.files to tlsCACerts as used elsewhere in this config file + # path to PEM encoded server certificate for the operations server + cert: + file: + + # path to PEM encoded server key for the operations server + key: + file: + + # require client certificate authentication to access all resources + clientAuthRequired: false + + # paths to PEM encoded ca certificates to trust for client authentication + clientRootCAs: + files: [] + +############################################################################### +# +# Metrics section +# copied from Fabric's core.yaml +############################################################################### +metrics: + # metrics provider is one of statsd, prometheus, or disabled + provider: prometheus + + # statsd configuration + statsd: + # network type: tcp or udp + network: udp + + # statsd server address + address: 127.0.0.1:8125 + + # the interval at which locally cached counters and gauges are pushed + # to statsd; timings are pushed immediately + writeInterval: 10s + + # prefix is prepended to all emitted statsd metrics + prefix: diff --git a/test/integration/e2e/configless/end_to_end_test.go b/test/integration/e2e/configless/end_to_end_test.go index e2a8b271ad..f109f0791f 100644 --- a/test/integration/e2e/configless/end_to_end_test.go +++ b/test/integration/e2e/configless/end_to_end_test.go @@ -29,5 +29,6 @@ func TestE2E(t *testing.T) { fabsdk.WithEndpointConfig(endpointConfigImpls...), fabsdk.WithCryptoSuiteConfig(cryptoConfigImpls...), fabsdk.WithIdentityConfig(identityConfigImpls...), + fabsdk.WithMetricsConfig(operationsConfigImpls...), ) } diff --git a/test/integration/e2e/configless/metricconfig_override_test.go b/test/integration/e2e/configless/metricconfig_override_test.go new file mode 100644 index 0000000000..0450c48413 --- /dev/null +++ b/test/integration/e2e/configless/metricconfig_override_test.go @@ -0,0 +1,51 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package configless + +import "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/metrics/cfg" + +// metricconfig_override_test.go is an example of programmatically configuring the sdk by injecting instances that implement Metricsonfig's functions (representing the sdk's configs) +// for the sake of overriding MetricsConfig integration tests, the structure variables below set the metrics to disabled as the standarad build does not use metrics. +// Using the pprof build tag, application developers can create sub interfaces of MetricsConfig with values similar to what is found in /test/fixtures/config/config_test.yaml +// the example implementation functions in this file can be overridden to load configs in any way that suits the client application needs + +var ( + operationConfig = cfg.OperationConfig{ + ListenAddress: "127.0.0.1:8080", + TLSEnabled: false, + TLSCertFile: "", + TLSKeyFile: "", + ClientAuthRequired: false, + ClientRootCAs: []string{}, + } + + metricConfig = cfg.MetricConfig{ + Provider: "disabled", + Statsd: cfg.Statsd{}, + } + + opConfigImpl = &exampleOperation{} + metricCfgImpl = &exampleMetric{} + operationsConfigImpls = []interface{}{ + opConfigImpl, + metricCfgImpl, + } +) + +type exampleOperation struct{} + +//OperationCfg overrides MetricsConfig's OperationConfig function which returns the operations config +func (m *exampleOperation) OperationCfg() cfg.OperationConfig { + return operationConfig +} + +type exampleMetric struct{} + +//MetricCfg overrides MetricsConfig's OperationConfig function which returns the operations config +func (m *exampleMetric) MetricCfg() cfg.MetricConfig { + return metricConfig +} diff --git a/test/performance/metrics/server.go b/test/performance/metrics/server.go deleted file mode 100644 index 10b83f3133..0000000000 --- a/test/performance/metrics/server.go +++ /dev/null @@ -1,173 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package metrics - -// TODO remove this package once the Fabric copy is imported - -import ( - "fmt" - "io" - "time" - - "sync" - - "github.com/pkg/errors" - "github.com/spf13/viper" - "github.com/uber-go/tally" - promreporter "github.com/uber-go/tally/prometheus" -) - -const ( - namespace string = "hyperledger_fabric" - - statsdReporterType = "statsd" - promReporterType = "prom" - - defaultReporterType = statsdReporterType - defaultInterval = 1 * time.Second - - defaultStatsdReporterFlushInterval = 2 * time.Second - defaultStatsdReporterFlushBytes = 1432 -) - -// RootScope tally.NoopScope is a scope that does nothing -var RootScope = tally.NoopScope -var rootScopeMutex = &sync.Mutex{} -var running bool - -// StatsdReporterOpts ... -type StatsdReporterOpts struct { - Address string - FlushInterval time.Duration - FlushBytes int -} - -// PromReporterOpts ... -type PromReporterOpts struct { - ListenAddress string -} - -// Opts ... -type Opts struct { - Reporter string - Interval time.Duration - Enabled bool - StatsdReporterOpts StatsdReporterOpts - PromReporterOpts PromReporterOpts -} - -// NewOpts create metrics options based config file. -// TODO: Currently this is only for peer node which uses global viper. -// As for orderer, which uses its local viper, we are unable to get -// metrics options with the function NewOpts() -func NewOpts(peerConfig *viper.Viper) Opts { - opts := Opts{} - opts.Enabled = peerConfig.GetBool("metrics.enabled") - if report := peerConfig.GetString("metrics.reporter"); report != "" { - opts.Reporter = report - } else { - opts.Reporter = defaultReporterType - } - if interval := peerConfig.GetDuration("metrics.interval"); interval > 0 { - opts.Interval = interval - } else { - opts.Interval = defaultInterval - } - - if opts.Reporter == statsdReporterType { - statsdOpts := StatsdReporterOpts{} - statsdOpts.Address = peerConfig.GetString("metrics.statsdReporter.address") - if flushInterval := peerConfig.GetDuration("metrics.statsdReporter.flushInterval"); flushInterval > 0 { - statsdOpts.FlushInterval = flushInterval - } else { - statsdOpts.FlushInterval = defaultStatsdReporterFlushInterval - } - if flushBytes := peerConfig.GetInt("metrics.statsdReporter.flushBytes"); flushBytes > 0 { - statsdOpts.FlushBytes = flushBytes - } else { - statsdOpts.FlushBytes = defaultStatsdReporterFlushBytes - } - opts.StatsdReporterOpts = statsdOpts - } - - if opts.Reporter == promReporterType { - promOpts := PromReporterOpts{} - promOpts.ListenAddress = peerConfig.GetString("metrics.promReporter.listenAddress") - opts.PromReporterOpts = promOpts - } - - return opts -} - -// Start starts metrics server -func Start(opts Opts) error { - if !opts.Enabled { - return errors.New("Unable to start metrics server because it is disabled") - } - rootScopeMutex.Lock() - defer rootScopeMutex.Unlock() - if !running { - rootScope, err := create(opts) - if err == nil { - running = true - RootScope = rootScope - } - return err - } - return errors.New("metrics server was already started") -} - -// Shutdown closes underlying resources used by metrics server -func Shutdown() error { - rootScopeMutex.Lock() - defer rootScopeMutex.Unlock() - if running { - var err error - if closer, ok := RootScope.(io.Closer); ok { - if err = closer.Close(); err != nil { - return err - } - } - running = false - RootScope = tally.NoopScope - return err - } - return nil -} - -func create(opts Opts) (rootScope tally.Scope, e error) { - if !opts.Enabled { - rootScope = tally.NoopScope - } else { - if opts.Interval <= 0 { - e = fmt.Errorf("invalid Interval option %d", opts.Interval) - return - } - var reporter tally.StatsReporter - var cachedReporter tally.CachedStatsReporter - switch opts.Reporter { - case statsdReporterType: - reporter, e = newStatsdReporter(opts.StatsdReporterOpts) - case promReporterType: - cachedReporter, e = newPromReporter(opts.PromReporterOpts) - default: - e = fmt.Errorf("not supported Reporter type %s", opts.Reporter) - return - } - if e != nil { - return - } - rootScope = newRootScope( - tally.ScopeOptions{ - Prefix: namespace, - Reporter: reporter, - CachedReporter: cachedReporter, - Separator: promreporter.DefaultSeparator, - }, opts.Interval) - } - return -} diff --git a/test/performance/metrics/tally_provider.go b/test/performance/metrics/tally_provider.go deleted file mode 100644 index 35daef9de4..0000000000 --- a/test/performance/metrics/tally_provider.go +++ /dev/null @@ -1,189 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package metrics - -// TODO remove this package once the Fabric copy is imported - -import ( - "errors" - "net/http" - "time" - - "net" - - "sort" - - "github.com/cactus/go-statsd-client/statsd" - "github.com/hyperledger/fabric-sdk-go/pkg/common/logging" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/uber-go/tally" - promreporter "github.com/uber-go/tally/prometheus" - statsdreporter "github.com/uber-go/tally/statsd" -) - -var logger = logging.NewLogger("perf_tally_provider") - -func newRootScope(opts tally.ScopeOptions, interval time.Duration) tally.Scope { - s, _ := tally.NewRootScope(opts, interval) - return s -} - -func newStatsdReporter(statsdReporterOpts StatsdReporterOpts) (tally.StatsReporter, error) { - if statsdReporterOpts.Address == "" { - return nil, errors.New("missing statsd server Address option") - } - - if statsdReporterOpts.FlushInterval <= 0 { - return nil, errors.New("missing statsd FlushInterval option") - } - - if statsdReporterOpts.FlushBytes <= 0 { - return nil, errors.New("missing statsd FlushBytes option") - } - - statter, err := statsd.NewBufferedClient(statsdReporterOpts.Address, - "", statsdReporterOpts.FlushInterval, statsdReporterOpts.FlushBytes) - if err != nil { - return nil, err - } - opts := statsdreporter.Options{} - reporter := statsdreporter.NewReporter(statter, opts) - statsdReporter := &statsdReporter{StatsReporter: reporter, statter: statter} - return statsdReporter, nil -} - -func newPromReporter(promReporterOpts PromReporterOpts) (promreporter.Reporter, error) { - if promReporterOpts.ListenAddress == "" { - return nil, errors.New("missing prometheus listenAddress option") - } - - opts := promreporter.Options{Registerer: prometheus.NewRegistry()} - reporter := promreporter.NewReporter(opts) - mux := http.NewServeMux() - handler := promReporterHTTPHandler(opts.Registerer.(*prometheus.Registry)) - mux.Handle("/metrics", handler) - server := &http.Server{Handler: mux} - addr := promReporterOpts.ListenAddress - if addr == "" { - addr = ":http" - } - listener, err := net.Listen("tcp", addr) - if err != nil { - return nil, err - } - promReporter := &promReporter{ - Reporter: reporter, - server: server, - registry: opts.Registerer.(*prometheus.Registry), - listener: listener} - go func() { - err := server.Serve(listener) - if err != nil { - logger.Warnf("failed to start registry server: %s", err) - } - }() - return promReporter, nil -} - -type statsdReporter struct { - tally.StatsReporter - statter statsd.Statter -} - -type promReporter struct { - promreporter.Reporter - server *http.Server - listener net.Listener - registry *prometheus.Registry -} - -func (r *statsdReporter) Close() error { - return r.statter.Close() -} - -func (r *statsdReporter) ReportCounter(name string, tags map[string]string, value int64) { - r.StatsReporter.ReportCounter(tagsToName(name, tags), tags, value) -} - -func (r *statsdReporter) ReportGauge(name string, tags map[string]string, value float64) { - r.StatsReporter.ReportGauge(tagsToName(name, tags), tags, value) -} - -func (r *statsdReporter) ReportTimer(name string, tags map[string]string, interval time.Duration) { - r.StatsReporter.ReportTimer(tagsToName(name, tags), tags, interval) -} - -func (r *statsdReporter) ReportHistogramValueSamples( - name string, - tags map[string]string, - buckets tally.Buckets, - bucketLowerBound, - bucketUpperBound float64, - samples int64, -) { - r.StatsReporter.ReportHistogramValueSamples(tagsToName(name, tags), tags, buckets, bucketLowerBound, bucketUpperBound, samples) -} - -func (r *statsdReporter) ReportHistogramDurationSamples( - name string, - tags map[string]string, - buckets tally.Buckets, - bucketLowerBound, - bucketUpperBound time.Duration, - samples int64, -) { - r.StatsReporter.ReportHistogramDurationSamples(tagsToName(name, tags), tags, buckets, bucketLowerBound, bucketUpperBound, samples) -} - -func (r *statsdReporter) Capabilities() tally.Capabilities { - return r -} - -func (r *statsdReporter) Reporting() bool { - return true -} - -func (r *statsdReporter) Tagging() bool { - return true -} - -func (r *promReporter) Close() error { - //TODO: Shutdown server gracefully? - // Close() is not a graceful way since it closes server immediately - err := r.server.Close() - if err != nil { - logger.Warnf("failed to close registry server: %s", err) - } - err = r.listener.Close() - if err != nil { - logger.Warnf("failed to close registrey listener: %s", err) - } - return err -} - -func (r *promReporter) HTTPHandler() http.Handler { - return promReporterHTTPHandler(r.registry) -} - -func promReporterHTTPHandler(registry prometheus.Gatherer) http.Handler { - return promhttp.HandlerFor(registry, promhttp.HandlerOpts{}) -} - -func tagsToName(name string, tags map[string]string) string { - var keys []string - for k := range tags { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, k := range keys { - name = name + promreporter.DefaultSeparator + k + "-" + tags[k] - } - - return name -} diff --git a/test/performance/pkg/client/channel/README.md b/test/performance/pkg/client/channel/README.md index 8abea80b79..ed5f2acd7f 100644 --- a/test/performance/pkg/client/channel/README.md +++ b/test/performance/pkg/client/channel/README.md @@ -3,7 +3,6 @@ Under the directory where this file resides, the test commands are run as shown under the below comments: ( - * on a Macbook Pro, warning messages are stripped out below for conciseness * Benchmark is using Go's test command with -bench=ExecuteTx * the -run=notest flag means execute a non-existant 'notest' in the current folder This will avoid running normal unit tests along with the benchmarks @@ -29,8 +28,15 @@ the benchmark and the mocked servers which decreases the overall performance results. To get exact performance data for this channel client of the Go SDK, one needs to run benchmarks against a real Fabric network with peers and orderers running in Docker containers. - Final Note: Performance collection using the Tally performance tool (see section below) now requires the SDK to be built with the pprof tag. - This means in order to collect Tally data via the Prometheus report, the below sample commands were updated to include `-tags pprof` + NOTE 2: The SDK config file must contain Fabric's perf configs in order to enable metrics collections. See this file for an example: + test/fixtures/config/config_test.yaml + + NOTE 3: With the update to Fabric's metrics API, new metrics are automatically added when running the benchmark (without any additional setup). + These are found in the statsd package and will show up in the Prometheus report as well: + internal/github.com/hyperledger/fabric/common/metrics/statsd/goruntime/collector.go + + Final Note: Performance collection using the Metrics performance tool (see section below) now requires the SDK to be built with the pprof tag. + This means in order to collect metrics data via the Prometheus report, the below sample commands were updated to include `-tags pprof` ) $ go test -tags pprof -run=notest -bench=ExecuteTx* @@ -74,42 +80,46 @@ BenchmarkExecuteTxParallel-8 500000 501436 ns/op 218011 B/op 3008 PASS ok github.com/hyperledger/fabric-sdk-go/test/performance/pkg/client/channel 529.397s -#Benchmark data in Tally (using Prometheus report) -The Channel Client's Execute and Query functions have been amended to collect tally counts and time spent executing these functions. +#Benchmark data (using Prometheus report) +The Channel Client's Execute and Query functions have been amended to collect metric counts and time spent executing these functions. -In order to support collecting the data, make sure to start the data collector server found in: -fabric-sdk-go/test/performance/metrics/server.go - -example of starting a data collector server is found in this benchmark (reference initAndStartMetricsServer() call) +In order to support collecting the data, make sure to start the data collector server. An example of starting a data collector server is found +in this benchmark (reference chClient.StartOperationsSystem() call) then start the Prometheus Docker container (an example docker compose config file is found at: fabric-sdk-go/test/performance/prometheus ) -finally run your sdk client and the perf data will be collected by the prometheus server. Navigate to +Finally run your sdk client and the perf data will be collected by the prometheus server. Navigate to 127.0.0.1:9095 to view the report. -Make sure the Go client is running and some channel communication activity has occured with a peer in order +Make sure the Go client is running and some channel communication activity has occurred with a peer in order to see collected performance data. -for the purpose of this channel client benchmark, once the Prometheus docker container is started, run the benchmark with long enough +For the purpose of this channel client benchmark, once the Prometheus docker container is started, run the benchmark with long enough run times and navigate to the address above to see data being collected (run with -benchtime=300s will show this data on the report as an example) If you would like to collect perf data into your version of Prometheus server (example dedicated performance environment), -make sure to add metrics calls using the 'metrics' packgage in this sdk -ie: "github.com/hyperledger/fabric-sdk-go/test/performance/metrics" +make sure to create new metrics instances and register them the same way as in the channel client package. +ie look at: "github.com/hyperledger/fabric-sdk-go/pkg/client/channel/chclientrun.go" to see how ClientMetrics is created and +metrics added in the code. +"github.com/hyperledger/fabric-sdk-go/pkg/client/channel/metrics.go" creates metrics structures to be used in the file above. + +currently, only channel client is configured with performance metrics (and operations system like Fabric). +To setup data collection in your client application, see this file for more details: +fabric-sdk-go/pkg/client/channel/chclient.go -for an example usage on how to setup data collection in your client application, see: fabric-sdk-go/pkg/client/channel/chclient.go +The file fabric-sdk-go/test/performance/pkg/client/channel/chclient_fixture_test.go is loading metrics configs from the file referenced in `configPath` variable. #Benchmark CPU & Memory performance analysis In order to generate profiling data for the chClient benchmark, the go test command can be extended to generate these. Note: If the below command complains about cpu.out or mem.out files are missing, create these files with empty content prior to running the command: -go test -v -run=notest -bench=ExecuteTx -benchtime=1s -outputdir ./bench1s -cpuprofile cpu.out -memprofilerate 1 -memprofile mem.out +go test -v -tags pprof -run=notest -bench=ExecuteTx -benchtime=1s -outputdir ./bench1s -cpuprofile cpu.out -memprofilerate 1 -memprofile mem.out once ./bench1s has a valid cpu.out and mem.out content, then we can use go pprof command to examine the perf data. diff --git a/test/performance/pkg/client/channel/chclient_test.go b/test/performance/pkg/client/channel/chclient_test.go index 5c18e70bca..78a49fca51 100644 --- a/test/performance/pkg/client/channel/chclient_test.go +++ b/test/performance/pkg/client/channel/chclient_test.go @@ -12,9 +12,6 @@ import ( "testing" "github.com/golang/protobuf/proto" - // TODO update metrics package with Fabric's copy, once officially released - // TODO and pinned into Go SDK with the below commented out import statement - //"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/metrics" "github.com/hyperledger/fabric-sdk-go/pkg/client/channel" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" @@ -24,13 +21,10 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/provider/chpvdr" "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" - // TODO remove below metrics declaration once Fabric's copy is ready to be used - "github.com/hyperledger/fabric-sdk-go/test/performance/metrics" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/cauthdsl" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/core/common/ccprovider" pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" "github.com/pkg/errors" - "github.com/spf13/viper" "google.golang.org/grpc/credentials" "google.golang.org/grpc/testdata" ) @@ -59,7 +53,6 @@ var ( chRq = channel.Request{ChaincodeID: "testCC", Fcn: "invoke", Args: [][]byte{[]byte("move"), []byte("b")}} endorserURL = fmt.Sprintf("%s:%d", testhost, testport) ordererURL = fmt.Sprintf("%s:%d", testBrodcasthost, testBroadcastport) - metricsConfig *viper.Viper ) func BenchmarkExecuteTx(b *testing.B) { @@ -94,35 +87,12 @@ func BenchmarkExecuteTxParallel(b *testing.B) { } func TestMain(m *testing.M) { - initAndStartMetricsServer() - setUp(m) r := m.Run() teardown() os.Exit(r) } -func initAndStartMetricsServer() bool { - metricsConfig = viper.New() - metricsConfig.SetConfigFile(testdata.Path(pathvar.Subst(configPath))) - err := metricsConfig.ReadInConfig() - if err != nil { - panic(fmt.Sprintf("perf metrics configs missing: %s", err)) - } - - opts := metrics.NewOpts(metricsConfig) - err = metrics.Start(opts) - if err != nil { - fmt.Println("******** Metrics server err **********: ", err) - if err.Error() == "Unable to start metrics server because it is disabled" { - return false - } - panic(fmt.Sprintf("failed to start metrics server: %s", err)) - } - fmt.Println("******** Metrics server started **********") - return true -} - func setUp(m *testing.M) { // do any setup here... tlsServerCertFile := testdata.Path(pathvar.Subst(peerTLSServerCert)) diff --git a/test/scripts/dependencies.sh b/test/scripts/dependencies.sh index f9e2b23c60..49525e46af 100755 --- a/test/scripts/dependencies.sh +++ b/test/scripts/dependencies.sh @@ -48,7 +48,7 @@ function installGoDep { function installGoMetalinter { declare repo="github.com/alecthomas/gometalinter" - declare revision="v2" + declare revision="v2.0.12" declare pkg="github.com/alecthomas/gometalinter"