code.vegaprotocol.io/vega@v0.79.0/datanode/metrics/prometheus.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package metrics
    17  
    18  import (
    19  	"fmt"
    20  	"log"
    21  	"net/http"
    22  	"net/url"
    23  	"strings"
    24  	"time"
    25  
    26  	"code.vegaprotocol.io/vega/core/events"
    27  	"code.vegaprotocol.io/vega/protos"
    28  
    29  	"github.com/pkg/errors"
    30  	"github.com/prometheus/client_golang/prometheus"
    31  	"github.com/prometheus/client_golang/prometheus/promhttp"
    32  )
    33  
    34  const (
    35  	// Gauge ...
    36  	Gauge instrument = iota
    37  	// Counter ...
    38  	Counter
    39  	// Histogram ...
    40  	Histogram
    41  	// Summary ...
    42  	Summary
    43  )
    44  
    45  var (
    46  	// ErrInstrumentNotSupported signals the specified instrument is not yet supported.
    47  	ErrInstrumentNotSupported = errors.New("instrument type unsupported")
    48  	// ErrInstrumentTypeMismatch signal the type of the instrument is not expected.
    49  	ErrInstrumentTypeMismatch = errors.New("instrument is not of the expected type")
    50  )
    51  
    52  var (
    53  	engineTime        *prometheus.CounterVec
    54  	eventHandlingTime *prometheus.CounterVec
    55  	flushHandlingTime *prometheus.CounterVec
    56  	eventCounter      *prometheus.CounterVec
    57  	sqlQueryTime      *prometheus.CounterVec
    58  	sqlQueryCounter   *prometheus.CounterVec
    59  	blockCounter      prometheus.Counter
    60  	blockHandlingTime prometheus.Counter
    61  	blockHeight       prometheus.Gauge
    62  
    63  	publishedEventsCounter         *prometheus.CounterVec
    64  	eventBusPublishedEventsCounter *prometheus.CounterVec
    65  
    66  	// Subscription gauge for each type.
    67  	subscriptionGauge         *prometheus.GaugeVec
    68  	eventBusSubscriptionGauge *prometheus.GaugeVec
    69  	eventBusConnectionGauge   prometheus.Gauge
    70  
    71  	// Call counters for each request type per API.
    72  	apiRequestCallCounter *prometheus.CounterVec
    73  	// Total time counters for each request type per API.
    74  	apiRequestTimeCounter *prometheus.CounterVec
    75  
    76  	lastSnapshotRowcount          prometheus.Gauge
    77  	lastSnapshotCurrentStateBytes prometheus.Gauge
    78  	lastSnapshotHistoryBytes      prometheus.Gauge
    79  	lastSnapshotSeconds           prometheus.Gauge
    80  
    81  	eventBufferWrittenCount prometheus.Counter
    82  	eventBufferReadCount    prometheus.Counter
    83  
    84  	networkHistoryIpfsStoreBytes prometheus.Gauge
    85  	// Data Node HTTP bindings that we will check against when updating HTTP metrics.
    86  	httpBindings *protos.Bindings
    87  
    88  	// Per table segment creation time.
    89  	networkHistoryCopiedRowsCounter *prometheus.CounterVec
    90  	networkHistoryCopyTimeCounter   *prometheus.CounterVec
    91  
    92  	batcherAddedEntities   *prometheus.CounterVec
    93  	batcherFlushedEntities *prometheus.CounterVec
    94  )
    95  
    96  // abstract prometheus types.
    97  type instrument int
    98  
    99  // combine all possible prometheus options + way to differentiate between regular or vector type.
   100  type instrumentOpts struct {
   101  	opts               prometheus.Opts
   102  	buckets            []float64
   103  	objectives         map[float64]float64
   104  	maxAge             time.Duration
   105  	ageBuckets, bufCap uint32
   106  	vectors            []string
   107  }
   108  
   109  type mi struct {
   110  	gaugeV     *prometheus.GaugeVec
   111  	gauge      prometheus.Gauge
   112  	counterV   *prometheus.CounterVec
   113  	counter    prometheus.Counter
   114  	histogramV *prometheus.HistogramVec
   115  	histogram  prometheus.Histogram
   116  	summaryV   *prometheus.SummaryVec
   117  	summary    prometheus.Summary
   118  }
   119  
   120  // MetricInstrument - template interface for mi type return value - only mock if needed, and only mock the funcs you use.
   121  type MetricInstrument interface {
   122  	Gauge() (prometheus.Gauge, error)
   123  	GaugeVec() (*prometheus.GaugeVec, error)
   124  	Counter() (prometheus.Counter, error)
   125  	CounterVec() (*prometheus.CounterVec, error)
   126  	Histogram() (prometheus.Histogram, error)
   127  	HistogramVec() (*prometheus.HistogramVec, error)
   128  	Summary() (prometheus.Summary, error)
   129  	SummaryVec() (*prometheus.SummaryVec, error)
   130  }
   131  
   132  // InstrumentOption - vararg for instrument options setting.
   133  type InstrumentOption func(o *instrumentOpts)
   134  
   135  // Vectors - configuration used to create a vector of a given interface, slice of label names.
   136  func Vectors(labels ...string) InstrumentOption {
   137  	return func(o *instrumentOpts) {
   138  		o.vectors = labels
   139  	}
   140  }
   141  
   142  // Help - set the help field on instrument.
   143  func Help(help string) InstrumentOption {
   144  	return func(o *instrumentOpts) {
   145  		o.opts.Help = help
   146  	}
   147  }
   148  
   149  // Namespace - set namespace.
   150  func Namespace(ns string) InstrumentOption {
   151  	return func(o *instrumentOpts) {
   152  		o.opts.Namespace = ns
   153  	}
   154  }
   155  
   156  // Subsystem - set subsystem... obviously.
   157  func Subsystem(s string) InstrumentOption {
   158  	return func(o *instrumentOpts) {
   159  		o.opts.Subsystem = s
   160  	}
   161  }
   162  
   163  // Labels set labels for instrument (similar to vector, but with given values).
   164  func Labels(labels map[string]string) InstrumentOption {
   165  	return func(o *instrumentOpts) {
   166  		o.opts.ConstLabels = labels
   167  	}
   168  }
   169  
   170  // Buckets - specific to histogram type.
   171  func Buckets(b []float64) InstrumentOption {
   172  	return func(o *instrumentOpts) {
   173  		o.buckets = b
   174  	}
   175  }
   176  
   177  // Objectives - specific to summary type.
   178  func Objectives(obj map[float64]float64) InstrumentOption {
   179  	return func(o *instrumentOpts) {
   180  		o.objectives = obj
   181  	}
   182  }
   183  
   184  // MaxAge - specific to summary type.
   185  func MaxAge(m time.Duration) InstrumentOption {
   186  	return func(o *instrumentOpts) {
   187  		o.maxAge = m
   188  	}
   189  }
   190  
   191  // AgeBuckets - specific to summary type.
   192  func AgeBuckets(ab uint32) InstrumentOption {
   193  	return func(o *instrumentOpts) {
   194  		o.ageBuckets = ab
   195  	}
   196  }
   197  
   198  // BufCap - specific to summary type.
   199  func BufCap(bc uint32) InstrumentOption {
   200  	return func(o *instrumentOpts) {
   201  		o.bufCap = bc
   202  	}
   203  }
   204  
   205  // addInstrument  configure and register new metrics instrument
   206  // this will, over time, be moved to use custom Registries, etc...
   207  func addInstrument(t instrument, name string, opts ...InstrumentOption) (*mi, error) {
   208  	var col prometheus.Collector
   209  	ret := mi{}
   210  	opt := instrumentOpts{
   211  		opts: prometheus.Opts{
   212  			Name: name,
   213  		},
   214  	}
   215  	// apply options
   216  	for _, o := range opts {
   217  		o(&opt)
   218  	}
   219  	switch t {
   220  	case Gauge:
   221  		o := opt.gauge()
   222  		if len(opt.vectors) == 0 {
   223  			ret.gauge = prometheus.NewGauge(o)
   224  			col = ret.gauge
   225  		} else {
   226  			ret.gaugeV = prometheus.NewGaugeVec(o, opt.vectors)
   227  			col = ret.gaugeV
   228  		}
   229  	case Counter:
   230  		o := opt.counter()
   231  		if len(opt.vectors) == 0 {
   232  			ret.counter = prometheus.NewCounter(o)
   233  			col = ret.counter
   234  		} else {
   235  			ret.counterV = prometheus.NewCounterVec(o, opt.vectors)
   236  			col = ret.counterV
   237  		}
   238  	case Histogram:
   239  		o := opt.histogram()
   240  		if len(opt.vectors) == 0 {
   241  			ret.histogram = prometheus.NewHistogram(o)
   242  			col = ret.histogram
   243  		} else {
   244  			ret.histogramV = prometheus.NewHistogramVec(o, opt.vectors)
   245  			col = ret.histogramV
   246  		}
   247  	case Summary:
   248  		o := opt.summary()
   249  		if len(opt.vectors) == 0 {
   250  			ret.summary = prometheus.NewSummary(o)
   251  			col = ret.summary
   252  		} else {
   253  			ret.summaryV = prometheus.NewSummaryVec(o, opt.vectors)
   254  			col = ret.summaryV
   255  		}
   256  	default:
   257  		return nil, ErrInstrumentNotSupported
   258  	}
   259  	if err := prometheus.Register(col); err != nil {
   260  		return nil, err
   261  	}
   262  	return &ret, nil
   263  }
   264  
   265  // Start enable metrics (given config).
   266  func Start(conf Config) {
   267  	if !conf.Enabled {
   268  		return
   269  	}
   270  	err := setupMetrics()
   271  	if err != nil {
   272  		panic("could not set up metrics")
   273  	}
   274  	http.Handle(conf.Path, promhttp.Handler())
   275  	go func() {
   276  		log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", conf.Port), nil))
   277  	}()
   278  }
   279  
   280  func (i instrumentOpts) gauge() prometheus.GaugeOpts {
   281  	return prometheus.GaugeOpts(i.opts)
   282  }
   283  
   284  func (i instrumentOpts) counter() prometheus.CounterOpts {
   285  	return prometheus.CounterOpts(i.opts)
   286  }
   287  
   288  func (i instrumentOpts) summary() prometheus.SummaryOpts {
   289  	return prometheus.SummaryOpts{
   290  		Name:        i.opts.Name,
   291  		Namespace:   i.opts.Namespace,
   292  		Subsystem:   i.opts.Subsystem,
   293  		ConstLabels: i.opts.ConstLabels,
   294  		Help:        i.opts.Help,
   295  		Objectives:  i.objectives,
   296  		MaxAge:      i.maxAge,
   297  		AgeBuckets:  i.ageBuckets,
   298  		BufCap:      i.bufCap,
   299  	}
   300  }
   301  
   302  func (i instrumentOpts) histogram() prometheus.HistogramOpts {
   303  	return prometheus.HistogramOpts{
   304  		Name:        i.opts.Name,
   305  		Namespace:   i.opts.Namespace,
   306  		Subsystem:   i.opts.Subsystem,
   307  		ConstLabels: i.opts.ConstLabels,
   308  		Help:        i.opts.Help,
   309  		Buckets:     i.buckets,
   310  	}
   311  }
   312  
   313  // Gauge returns a prometheus Gauge instrument.
   314  func (m mi) Gauge() (prometheus.Gauge, error) {
   315  	if m.gauge == nil {
   316  		return nil, ErrInstrumentTypeMismatch
   317  	}
   318  	return m.gauge, nil
   319  }
   320  
   321  // GaugeVec returns a prometheus GaugeVec instrument.
   322  func (m mi) GaugeVec() (*prometheus.GaugeVec, error) {
   323  	if m.gaugeV == nil {
   324  		return nil, ErrInstrumentTypeMismatch
   325  	}
   326  	return m.gaugeV, nil
   327  }
   328  
   329  // Counter returns a prometheus Counter instrument.
   330  func (m mi) Counter() (prometheus.Counter, error) {
   331  	if m.counter == nil {
   332  		return nil, ErrInstrumentTypeMismatch
   333  	}
   334  	return m.counter, nil
   335  }
   336  
   337  // CounterVec returns a prometheus CounterVec instrument.
   338  func (m mi) CounterVec() (*prometheus.CounterVec, error) {
   339  	if m.counterV == nil {
   340  		return nil, ErrInstrumentTypeMismatch
   341  	}
   342  	return m.counterV, nil
   343  }
   344  
   345  func (m mi) Histogram() (prometheus.Histogram, error) {
   346  	if m.histogram == nil {
   347  		return nil, ErrInstrumentTypeMismatch
   348  	}
   349  	return m.histogram, nil
   350  }
   351  
   352  func (m mi) HistogramVec() (*prometheus.HistogramVec, error) {
   353  	if m.histogramV == nil {
   354  		return nil, ErrInstrumentTypeMismatch
   355  	}
   356  	return m.histogramV, nil
   357  }
   358  
   359  func (m mi) Summary() (prometheus.Summary, error) {
   360  	if m.summary == nil {
   361  		return nil, ErrInstrumentTypeMismatch
   362  	}
   363  	return m.summary, nil
   364  }
   365  
   366  func (m mi) SummaryVec() (*prometheus.SummaryVec, error) {
   367  	if m.summaryV == nil {
   368  		return nil, ErrInstrumentTypeMismatch
   369  	}
   370  	return m.summaryV, nil
   371  }
   372  
   373  func setupMetrics() error {
   374  	// instrument with time histogram for blocks
   375  	h, err := addInstrument(
   376  		Counter,
   377  		"engine_seconds_total",
   378  		Namespace("datanode"),
   379  		Vectors("market", "engine", "fn"),
   380  	)
   381  	if err != nil {
   382  		return err
   383  	}
   384  	est, err := h.CounterVec()
   385  	if err != nil {
   386  		return err
   387  	}
   388  	engineTime = est
   389  
   390  	h, err = addInstrument(
   391  		Counter,
   392  		"flush_handling_seconds_total",
   393  		Namespace("datanode"),
   394  		Vectors("subscriber"),
   395  	)
   396  	if err != nil {
   397  		return err
   398  	}
   399  	fht, err := h.CounterVec()
   400  	if err != nil {
   401  		return err
   402  	}
   403  	flushHandlingTime = fht
   404  
   405  	// eventHandlingTime
   406  	h, err = addInstrument(
   407  		Counter,
   408  		"event_handling_seconds_total",
   409  		Namespace("datanode"),
   410  		Vectors("type", "subscriber", "event"),
   411  	)
   412  	if err != nil {
   413  		return err
   414  	}
   415  	eht, err := h.CounterVec()
   416  	if err != nil {
   417  		return err
   418  	}
   419  	eventHandlingTime = eht
   420  
   421  	h, err = addInstrument(
   422  		Counter,
   423  		"published_event_count_total",
   424  		Namespace("datanode"),
   425  		Vectors("event"),
   426  	)
   427  	if err != nil {
   428  		return err
   429  	}
   430  	sec, err := h.CounterVec()
   431  	if err != nil {
   432  		return err
   433  	}
   434  	publishedEventsCounter = sec
   435  
   436  	h, err = addInstrument(
   437  		Counter,
   438  		"event_bus_published_event_count_total",
   439  		Namespace("datanode"),
   440  		Vectors("event"),
   441  	)
   442  	if err != nil {
   443  		return err
   444  	}
   445  	sec, err = h.CounterVec()
   446  	if err != nil {
   447  		return err
   448  	}
   449  	eventBusPublishedEventsCounter = sec
   450  
   451  	// eventCount
   452  	h, err = addInstrument(
   453  		Counter,
   454  		"event_count_total",
   455  		Namespace("datanode"),
   456  		Vectors("event"),
   457  	)
   458  	if err != nil {
   459  		return err
   460  	}
   461  	ec, err := h.CounterVec()
   462  	if err != nil {
   463  		return err
   464  	}
   465  	eventCounter = ec
   466  
   467  	h, err = addInstrument(
   468  		Counter,
   469  		"network_history_copied_rows_total",
   470  		Namespace("datanode"),
   471  		Vectors("table"),
   472  	)
   473  	if err != nil {
   474  		return err
   475  	}
   476  	cr, err := h.CounterVec()
   477  	if err != nil {
   478  		return err
   479  	}
   480  	networkHistoryCopiedRowsCounter = cr
   481  
   482  	h, err = addInstrument(
   483  		Counter,
   484  		"network_history_copy_time_total",
   485  		Namespace("datanode"),
   486  		Vectors("table"),
   487  	)
   488  	if err != nil {
   489  		return err
   490  	}
   491  	ct, err := h.CounterVec()
   492  	if err != nil {
   493  		return err
   494  	}
   495  	networkHistoryCopyTimeCounter = ct
   496  
   497  	h, err = addInstrument(
   498  		Counter,
   499  		"batcher_added_entities",
   500  		Namespace("datanode"),
   501  		Vectors("table"),
   502  	)
   503  	if err != nil {
   504  		return err
   505  	}
   506  	baet, err := h.CounterVec()
   507  	if err != nil {
   508  		return err
   509  	}
   510  	batcherAddedEntities = baet
   511  
   512  	h, err = addInstrument(
   513  		Counter,
   514  		"batcher_flushed_entities",
   515  		Namespace("datanode"),
   516  		Vectors("table"),
   517  	)
   518  	if err != nil {
   519  		return err
   520  	}
   521  	bfe, err := h.CounterVec()
   522  	if err != nil {
   523  		return err
   524  	}
   525  	batcherFlushedEntities = bfe
   526  
   527  	// sqlQueryTime
   528  	h, err = addInstrument(
   529  		Counter,
   530  		"sql_query_seconds_total",
   531  		Namespace("datanode"),
   532  		Vectors("store", "query"),
   533  	)
   534  	if err != nil {
   535  		return err
   536  	}
   537  	sqt, err := h.CounterVec()
   538  	if err != nil {
   539  		return err
   540  	}
   541  	sqlQueryTime = sqt
   542  
   543  	// sqlQueryCounter
   544  	h, err = addInstrument(
   545  		Counter,
   546  		"sql_query_count",
   547  		Namespace("datanode"),
   548  		Vectors("store", "query"),
   549  	)
   550  	if err != nil {
   551  		return err
   552  	}
   553  	qc, err := h.CounterVec()
   554  	if err != nil {
   555  		return err
   556  	}
   557  	sqlQueryCounter = qc
   558  
   559  	h, err = addInstrument(
   560  		Counter,
   561  		"blocks_handling_time_seconds_total",
   562  		Namespace("datanode"),
   563  		Vectors(),
   564  		Help("Total time handling blocks"),
   565  	)
   566  	if err != nil {
   567  		return err
   568  	}
   569  	bht, err := h.Counter()
   570  	if err != nil {
   571  		return err
   572  	}
   573  	blockHandlingTime = bht
   574  
   575  	h, err = addInstrument(
   576  		Counter,
   577  		"blocks_total",
   578  		Namespace("datanode"),
   579  		Vectors(),
   580  		Help("Number of blocks processed"),
   581  	)
   582  	if err != nil {
   583  		return err
   584  	}
   585  	bt, err := h.Counter()
   586  	if err != nil {
   587  		return err
   588  	}
   589  	blockCounter = bt
   590  
   591  	h, err = addInstrument(
   592  		Counter,
   593  		"event_buffer_written_count",
   594  		Namespace("datanode"),
   595  		Vectors(),
   596  		Help("Total number of event written to the event buffer"),
   597  	)
   598  	if err != nil {
   599  		return err
   600  	}
   601  	ebwc, err := h.Counter()
   602  	if err != nil {
   603  		return err
   604  	}
   605  	eventBufferWrittenCount = ebwc
   606  
   607  	h, err = addInstrument(
   608  		Counter,
   609  		"event_buffer_read_count",
   610  		Namespace("datanode"),
   611  		Vectors(),
   612  		Help("Total number of events read from the event buffer"),
   613  	)
   614  	if err != nil {
   615  		return err
   616  	}
   617  	ebrc, err := h.Counter()
   618  	if err != nil {
   619  		return err
   620  	}
   621  	eventBufferReadCount = ebrc
   622  
   623  	h, err = addInstrument(
   624  		Gauge,
   625  		"block_height",
   626  		Namespace("datanode"),
   627  		Vectors(),
   628  		Help("Current block height"),
   629  	)
   630  	if err != nil {
   631  		return err
   632  	}
   633  	bh, err := h.Gauge()
   634  	if err != nil {
   635  		return err
   636  	}
   637  	blockHeight = bh
   638  
   639  	h, err = addInstrument(
   640  		Gauge,
   641  		"last_snapshot_rowcount",
   642  		Namespace("datanode"),
   643  		Vectors(),
   644  		Help("Last Snapshot Row Count"),
   645  	)
   646  	if err != nil {
   647  		return err
   648  	}
   649  	lsr, err := h.Gauge()
   650  	if err != nil {
   651  		return err
   652  	}
   653  	lastSnapshotRowcount = lsr
   654  
   655  	h, err = addInstrument(
   656  		Gauge,
   657  		"last_snapshot_history_bytes",
   658  		Namespace("datanode"),
   659  		Vectors(),
   660  		Help("The compressed byte size of the last snapshots history data"),
   661  	)
   662  	if err != nil {
   663  		return err
   664  	}
   665  	lshb, err := h.Gauge()
   666  	if err != nil {
   667  		return err
   668  	}
   669  	lastSnapshotHistoryBytes = lshb
   670  
   671  	h, err = addInstrument(
   672  		Gauge,
   673  		"last_snapshot_current_state_bytes",
   674  		Namespace("datanode"),
   675  		Vectors(),
   676  		Help("The compressed byte size of the last snapshots current state data"),
   677  	)
   678  	if err != nil {
   679  		return err
   680  	}
   681  	lscs, err := h.Gauge()
   682  	if err != nil {
   683  		return err
   684  	}
   685  	lastSnapshotCurrentStateBytes = lscs
   686  
   687  	h, err = addInstrument(
   688  		Gauge,
   689  		"last_snapshot_seconds",
   690  		Namespace("datanode"),
   691  		Vectors(),
   692  		Help("Last Snapshot Time Taken in Seconds"),
   693  	)
   694  	if err != nil {
   695  		return err
   696  	}
   697  	lss, err := h.Gauge()
   698  	if err != nil {
   699  		return err
   700  	}
   701  	lastSnapshotSeconds = lss
   702  
   703  	h, err = addInstrument(
   704  		Gauge,
   705  		"networkhistory_ipfs_store_bytes",
   706  		Namespace("datanode"),
   707  		Vectors(),
   708  		Help("The size in bytes of the network history ipfs store"),
   709  	)
   710  	if err != nil {
   711  		return err
   712  	}
   713  	dsb, err := h.Gauge()
   714  	if err != nil {
   715  		return err
   716  	}
   717  	networkHistoryIpfsStoreBytes = dsb
   718  
   719  	//
   720  	// API usage metrics start here
   721  	//
   722  
   723  	if h, err = addInstrument(
   724  		Gauge,
   725  		"active_subscriptions",
   726  		Namespace("datanode"),
   727  		Vectors("apiType", "eventType"),
   728  		Help("Number of active subscriptions"),
   729  	); err != nil {
   730  		return err
   731  	}
   732  
   733  	if subscriptionGauge, err = h.GaugeVec(); err != nil {
   734  		return err
   735  	}
   736  
   737  	if h, err = addInstrument(
   738  		Gauge,
   739  		"event_bus_active_subscriptions",
   740  		Namespace("datanode"),
   741  		Vectors("eventType"),
   742  		Help("Number of active subscriptions by type to the event bus"),
   743  	); err != nil {
   744  		return err
   745  	}
   746  
   747  	if eventBusSubscriptionGauge, err = h.GaugeVec(); err != nil {
   748  		return err
   749  	}
   750  
   751  	if h, err = addInstrument(
   752  		Gauge,
   753  		"event_bus_active_connections",
   754  		Namespace("datanode"),
   755  		Help("Number of active connections to the event bus"),
   756  	); err != nil {
   757  		return err
   758  	}
   759  	ac, err := h.Gauge()
   760  	if err != nil {
   761  		return err
   762  	}
   763  	eventBusConnectionGauge = ac
   764  
   765  	httpBindings, err = protos.DataNodeBindings()
   766  	if err != nil {
   767  		return err
   768  	}
   769  	// Number of calls to each request type
   770  	h, err = addInstrument(
   771  		Counter,
   772  		"request_count_total",
   773  		Namespace("datanode"),
   774  		Vectors("apiType", "requestType"),
   775  		Help("Count of API requests"),
   776  	)
   777  	if err != nil {
   778  		return err
   779  	}
   780  	rc, err := h.CounterVec()
   781  	if err != nil {
   782  		return err
   783  	}
   784  	apiRequestCallCounter = rc
   785  
   786  	// Total time for calls to each request type for each api type
   787  	h, err = addInstrument(
   788  		Counter,
   789  		"request_time_total",
   790  		Namespace("datanode"),
   791  		Vectors("apiType", "requestType"),
   792  		Help("Total time spent in each API request"),
   793  	)
   794  	if err != nil {
   795  		return err
   796  	}
   797  	rpac, err := h.CounterVec()
   798  	if err != nil {
   799  		return err
   800  	}
   801  	apiRequestTimeCounter = rpac
   802  
   803  	return nil
   804  }
   805  
   806  func AddBlockHandlingTime(duration time.Duration) {
   807  	if blockHandlingTime != nil {
   808  		blockHandlingTime.Add(duration.Seconds())
   809  	}
   810  }
   811  
   812  func EventBufferWrittenCountInc() {
   813  	if eventBufferWrittenCount == nil {
   814  		return
   815  	}
   816  	eventBufferWrittenCount.Inc()
   817  }
   818  
   819  func EventBufferReadCountInc() {
   820  	if eventBufferReadCount == nil {
   821  		return
   822  	}
   823  	eventBufferReadCount.Inc()
   824  }
   825  
   826  func BlockCounterInc(labelValues ...string) {
   827  	if blockCounter == nil {
   828  		return
   829  	}
   830  	blockCounter.Inc()
   831  }
   832  
   833  func EventCounterInc(labelValues ...string) {
   834  	if eventCounter == nil {
   835  		return
   836  	}
   837  	eventCounter.WithLabelValues(labelValues...).Inc()
   838  }
   839  
   840  func PublishedEventsAdd(event string, eventCount float64) {
   841  	if publishedEventsCounter == nil {
   842  		return
   843  	}
   844  
   845  	publishedEventsCounter.WithLabelValues(event).Add(eventCount)
   846  }
   847  
   848  func EventBusPublishedEventsAdd(event string, eventCount float64) {
   849  	if eventBusPublishedEventsCounter == nil {
   850  		return
   851  	}
   852  
   853  	eventBusPublishedEventsCounter.WithLabelValues(event).Add(eventCount)
   854  }
   855  
   856  func SetBlockHeight(height float64) {
   857  	if blockHeight == nil {
   858  		return
   859  	}
   860  	blockHeight.Set(height)
   861  }
   862  
   863  func SetLastSnapshotRowcount(count float64) {
   864  	if lastSnapshotRowcount == nil {
   865  		return
   866  	}
   867  	lastSnapshotRowcount.Set(count)
   868  }
   869  
   870  func SetLastSnapshotCurrentStateBytes(bytes float64) {
   871  	if lastSnapshotCurrentStateBytes == nil {
   872  		return
   873  	}
   874  	lastSnapshotCurrentStateBytes.Set(bytes)
   875  }
   876  
   877  func SetLastSnapshotHistoryBytes(bytes float64) {
   878  	if lastSnapshotHistoryBytes == nil {
   879  		return
   880  	}
   881  	lastSnapshotHistoryBytes.Set(bytes)
   882  }
   883  
   884  func SetLastSnapshotSeconds(seconds float64) {
   885  	if lastSnapshotSeconds == nil {
   886  		return
   887  	}
   888  	lastSnapshotSeconds.Set(seconds)
   889  }
   890  
   891  func SetNetworkHistoryIpfsStoreBytes(bytes float64) {
   892  	if networkHistoryIpfsStoreBytes == nil {
   893  		return
   894  	}
   895  	networkHistoryIpfsStoreBytes.Set(bytes)
   896  }
   897  
   898  // APIRequestAndTimeREST updates the metrics for REST API calls.
   899  func APIRequestAndTimeREST(method, request string, time float64) {
   900  	if apiRequestCallCounter == nil || apiRequestTimeCounter == nil || httpBindings == nil {
   901  		return
   902  	}
   903  
   904  	const (
   905  		invalid    = "invalid route"
   906  		invalidURL = "invalid url"
   907  		prefix     = "/api/v2/"
   908  	)
   909  
   910  	if !httpBindings.HasRoute(method, request) {
   911  		apiRequestCallCounter.WithLabelValues("REST", invalid).Inc()
   912  		apiRequestTimeCounter.WithLabelValues("REST", invalid).Add(time)
   913  		return
   914  	}
   915  
   916  	parsed, err := url.Parse(request)
   917  	if err != nil {
   918  		apiRequestCallCounter.WithLabelValues("REST", invalidURL).Inc()
   919  		apiRequestTimeCounter.WithLabelValues("REST", invalidURL).Add(time)
   920  		return
   921  	}
   922  
   923  	trimmedPath := strings.TrimPrefix(parsed.Path, prefix)
   924  
   925  	// Trim the URI down to something useful
   926  	if strings.Count(trimmedPath, "/") >= 1 {
   927  		trimmedPath = trimmedPath[:strings.Index(trimmedPath, "/")]
   928  	}
   929  
   930  	apiRequestCallCounter.WithLabelValues("REST", trimmedPath).Inc()
   931  	apiRequestTimeCounter.WithLabelValues("REST", trimmedPath).Add(time)
   932  }
   933  
   934  // APIRequestAndTimeGraphQL updates the metrics for GraphQL API calls.
   935  func APIRequestAndTimeGraphQL(request string, time float64) {
   936  	if apiRequestCallCounter == nil || apiRequestTimeCounter == nil {
   937  		return
   938  	}
   939  	apiRequestCallCounter.WithLabelValues("GraphQL", request).Inc()
   940  	apiRequestTimeCounter.WithLabelValues("GraphQL", request).Add(time)
   941  }
   942  
   943  // StartAPIRequestAndTimeGRPC updates the metrics for GRPC API calls.
   944  func StartAPIRequestAndTimeGRPC(request string) func() {
   945  	startTime := time.Now()
   946  	return func() {
   947  		if apiRequestCallCounter == nil || apiRequestTimeCounter == nil {
   948  			return
   949  		}
   950  		apiRequestCallCounter.WithLabelValues("GRPC", request).Inc()
   951  		duration := time.Since(startTime).Seconds()
   952  		apiRequestTimeCounter.WithLabelValues("GRPC", request).Add(duration)
   953  	}
   954  }
   955  
   956  func IncrementBatcherAddedEntities(table string) {
   957  	if batcherAddedEntities == nil {
   958  		return
   959  	}
   960  	batcherAddedEntities.WithLabelValues(table).Add(1)
   961  }
   962  
   963  func BatcherFlushedEntitiesAdd(table string, flushed int) {
   964  	if batcherFlushedEntities == nil {
   965  		return
   966  	}
   967  	batcherFlushedEntities.WithLabelValues(table).Add(float64(flushed))
   968  }
   969  
   970  func NetworkHistoryRowsCopied(table string, rowsCopied int64) {
   971  	if networkHistoryCopiedRowsCounter == nil {
   972  		return
   973  	}
   974  	networkHistoryCopiedRowsCounter.WithLabelValues(table).Add(float64(rowsCopied))
   975  }
   976  
   977  func StartNetworkHistoryCopy(table string) func() {
   978  	startTime := time.Now()
   979  	return func() {
   980  		if networkHistoryCopyTimeCounter == nil {
   981  			return
   982  		}
   983  		duration := time.Since(startTime).Seconds()
   984  		networkHistoryCopyTimeCounter.WithLabelValues(table).Add(duration)
   985  	}
   986  }
   987  
   988  func StartSQLQuery(store string, query string) func() {
   989  	startTime := time.Now()
   990  	return func() {
   991  		if sqlQueryTime == nil || sqlQueryCounter == nil {
   992  			return
   993  		}
   994  		sqlQueryCounter.WithLabelValues(store, query).Inc()
   995  		duration := time.Since(startTime).Seconds()
   996  		sqlQueryTime.WithLabelValues(store, query).Add(duration)
   997  	}
   998  }
   999  
  1000  func StartActiveSubscriptionCountGRPC(subscribedToType string) func() {
  1001  	if subscriptionGauge == nil {
  1002  		return func() {}
  1003  	}
  1004  
  1005  	subscriptionGauge.WithLabelValues("GRPC", subscribedToType).Inc()
  1006  	return func() {
  1007  		subscriptionGauge.WithLabelValues("GRPC", subscribedToType).Dec()
  1008  	}
  1009  }
  1010  
  1011  func StartActiveEventBusConnection() func() {
  1012  	if eventBusConnectionGauge == nil {
  1013  		return func() {}
  1014  	}
  1015  
  1016  	eventBusConnectionGauge.Inc()
  1017  	return func() {
  1018  		eventBusConnectionGauge.Dec()
  1019  	}
  1020  }
  1021  
  1022  func StartEventBusActiveSubscriptionCount(eventTypes []events.Type) {
  1023  	if eventBusSubscriptionGauge == nil {
  1024  		return
  1025  	}
  1026  
  1027  	for _, eventType := range eventTypes {
  1028  		eventBusSubscriptionGauge.WithLabelValues(eventType.String()).Inc()
  1029  	}
  1030  }
  1031  
  1032  func StopEventBusActiveSubscriptionCount(eventTypes []events.Type) {
  1033  	if eventBusSubscriptionGauge == nil {
  1034  		return
  1035  	}
  1036  
  1037  	for _, eventType := range eventTypes {
  1038  		eventBusSubscriptionGauge.WithLabelValues(eventType.String()).Dec()
  1039  	}
  1040  }