diff --git a/internal/apiserver/server.go b/internal/apiserver/server.go index dab0c90418..712d08d277 100644 --- a/internal/apiserver/server.go +++ b/internal/apiserver/server.go @@ -112,7 +112,7 @@ func (as *apiServer) Serve(ctx context.Context, o orchestrator.Orchestrator) (er } if as.metricsEnabled { - metricsHTTPServer, err := newHTTPServer(ctx, "metrics", as.createMetricsMuxRouter(ctx), metricsErrChan, metricsConfigPrefix) + metricsHTTPServer, err := newHTTPServer(ctx, "metrics", as.createMetricsMuxRouter(), metricsErrChan, metricsConfigPrefix) if err != nil { return err } @@ -494,7 +494,7 @@ func (as *apiServer) createAdminMuxRouter(o orchestrator.Orchestrator) *mux.Rout return r } -func (as *apiServer) createMetricsMuxRouter(_ context.Context) *mux.Router { +func (as *apiServer) createMetricsMuxRouter() *mux.Router { r := mux.NewRouter() r.Path(config.GetString(config.MetricsPath)).Handler(promhttp.InstrumentMetricHandler(metrics.Registry(), diff --git a/internal/apiserver/server_test.go b/internal/apiserver/server_test.go index 36d6b1f367..eab6938e8c 100644 --- a/internal/apiserver/server_test.go +++ b/internal/apiserver/server_test.go @@ -27,12 +27,11 @@ import ( "testing" "time" - "github.com/hyperledger/firefly/internal/metrics" - "github.com/getkin/kin-openapi/openapi3" "github.com/gorilla/mux" "github.com/hyperledger/firefly/internal/config" "github.com/hyperledger/firefly/internal/i18n" + "github.com/hyperledger/firefly/internal/metrics" "github.com/hyperledger/firefly/internal/oapispec" "github.com/hyperledger/firefly/mocks/orchestratormocks" "github.com/stretchr/testify/assert" diff --git a/internal/batchpin/batchpin.go b/internal/batchpin/batchpin.go index 97869c7a94..f5a7db6ca5 100644 --- a/internal/batchpin/batchpin.go +++ b/internal/batchpin/batchpin.go @@ -19,7 +19,9 @@ package batchpin import ( "context" + "github.com/hyperledger/firefly/internal/config" "github.com/hyperledger/firefly/internal/identity" + "github.com/hyperledger/firefly/internal/metrics" "github.com/hyperledger/firefly/pkg/blockchain" "github.com/hyperledger/firefly/pkg/database" "github.com/hyperledger/firefly/pkg/fftypes" @@ -30,21 +32,22 @@ type Submitter interface { } type batchPinSubmitter struct { - database database.Plugin - identity identity.Manager - blockchain blockchain.Plugin + database database.Plugin + identity identity.Manager + blockchain blockchain.Plugin + metricsEnabled bool } func NewBatchPinSubmitter(di database.Plugin, im identity.Manager, bi blockchain.Plugin) Submitter { return &batchPinSubmitter{ - database: di, - identity: im, - blockchain: bi, + database: di, + identity: im, + blockchain: bi, + metricsEnabled: config.GetBool(config.MetricsEnabled), } } func (bp *batchPinSubmitter) SubmitPinnedBatch(ctx context.Context, batch *fftypes.Batch, contexts []*fftypes.Bytes32) error { - tx := &fftypes.Transaction{ ID: batch.Payload.TX.ID, Subject: fftypes.TransactionSubject{ @@ -75,6 +78,9 @@ func (bp *batchPinSubmitter) SubmitPinnedBatch(ctx context.Context, batch *fftyp return err } + if bp.metricsEnabled { + metrics.BatchPinCounter.Inc() + } // Write the batch pin to the blockchain return bp.blockchain.SubmitBatchPin(ctx, op.ID, nil /* TODO: ledger selection */, batch.Key, &blockchain.BatchPin{ Namespace: batch.Namespace, diff --git a/internal/batchpin/batchpin_test.go b/internal/batchpin/batchpin_test.go index 03d4069f02..2b603aea6f 100644 --- a/internal/batchpin/batchpin_test.go +++ b/internal/batchpin/batchpin_test.go @@ -21,6 +21,8 @@ import ( "fmt" "testing" + "github.com/hyperledger/firefly/internal/config" + "github.com/hyperledger/firefly/internal/metrics" "github.com/hyperledger/firefly/mocks/blockchainmocks" "github.com/hyperledger/firefly/mocks/databasemocks" "github.com/hyperledger/firefly/mocks/identitymanagermocks" @@ -29,6 +31,8 @@ import ( "github.com/stretchr/testify/mock" ) +var utConfPrefix = config.NewPluginConfig("metrics") + func newTestBatchPinSubmitter(t *testing.T) *batchPinSubmitter { mdi := &databasemocks.Plugin{} mim := &identitymanagermocks.Manager{} @@ -38,7 +42,6 @@ func newTestBatchPinSubmitter(t *testing.T) *batchPinSubmitter { } func TestSubmitPinnedBatchOk(t *testing.T) { - bp := newTestBatchPinSubmitter(t) ctx := context.Background() @@ -70,7 +73,42 @@ func TestSubmitPinnedBatchOk(t *testing.T) { err := bp.SubmitPinnedBatch(ctx, batch, contexts) assert.NoError(t, err) +} + +func TestSubmitPinnedBatchWithMetricsOk(t *testing.T) { + metrics.Registry() + config.Set(config.MetricsEnabled, true) + bp := newTestBatchPinSubmitter(t) + ctx := context.Background() + + mbi := bp.blockchain.(*blockchainmocks.Plugin) + mdi := bp.database.(*databasemocks.Plugin) + + batch := &fftypes.Batch{ + ID: fftypes.NewUUID(), + Identity: fftypes.Identity{ + Author: "id1", + Key: "0x12345", + }, + Payload: fftypes.BatchPayload{ + TX: fftypes.TransactionRef{ + ID: fftypes.NewUUID(), + }, + }, + } + contexts := []*fftypes.Bytes32{} + mdi.On("UpsertTransaction", ctx, mock.Anything, false).Return(nil) + mdi.On("UpsertOperation", ctx, mock.MatchedBy(func(op *fftypes.Operation) bool { + assert.Equal(t, fftypes.OpTypeBlockchainBatchPin, op.Type) + assert.Equal(t, "ut", op.Plugin) + assert.Equal(t, *batch.Payload.TX.ID, *op.Transaction) + return true + }), false).Return(nil) + mbi.On("SubmitBatchPin", ctx, mock.Anything, (*fftypes.UUID)(nil), "0x12345", mock.Anything).Return(nil) + + err := bp.SubmitPinnedBatch(ctx, batch, contexts) + assert.NoError(t, err) } func TestSubmitPinnedBatchOpFail(t *testing.T) { diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 594d118009..4d4e837d12 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -16,21 +16,40 @@ package metrics -import "github.com/prometheus/client_golang/prometheus" +import ( + "github.com/prometheus/client_golang/prometheus" +) var registry *prometheus.Registry +var BatchPinCounter prometheus.Counter + +// MetricsBatchPin is the prometheus metric for total number of batch pins submitted +var MetricsBatchPin = "ff_batchpin_total" // Registry returns FireFly's customized Prometheus registry func Registry() *prometheus.Registry { if registry == nil { + initMetricsCollectors() registry = prometheus.NewRegistry() - registry.MustRegister(prometheus.NewGoCollector()) - registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{})) + registerMetricsCollectors() } return registry } +func initMetricsCollectors() { + BatchPinCounter = prometheus.NewCounter(prometheus.CounterOpts{ + Name: MetricsBatchPin, + Help: "Number of batch pins submitted", + }) +} + +func registerMetricsCollectors() { + registry.MustRegister(prometheus.NewGoCollector()) + registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{})) + registry.MustRegister(BatchPinCounter) +} + // Clear will reset the Prometheus metrics registry, useful for testing func Clear() { registry = nil