github.com/lzy4123/fabric@v2.1.1+incompatible/orderer/consensus/kafka/metrics.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package kafka
     8  
     9  import (
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/hyperledger/fabric/common/metrics"
    14  
    15  	gometrics "github.com/rcrowley/go-metrics"
    16  )
    17  
    18  /*
    19  
    20   Per the documentation at: https://godoc.org/github.com/Shopify/sarama Sarama exposes the following set of metrics:
    21  
    22   +----------------------------------------------+------------+---------------------------------------------------------------+
    23   | Name                                         | Type       | Description                                                   |
    24   +----------------------------------------------+------------+---------------------------------------------------------------+
    25   | incoming-byte-rate                           | meter      | Bytes/second read off all brokers                             |
    26   | incoming-byte-rate-for-broker-<broker-id>    | meter      | Bytes/second read off a given broker                          |
    27   | outgoing-byte-rate                           | meter      | Bytes/second written off all brokers                          |
    28   | outgoing-byte-rate-for-broker-<broker-id>    | meter      | Bytes/second written off a given broker                       |
    29   | request-rate                                 | meter      | Requests/second sent to all brokers                           |
    30   | request-rate-for-broker-<broker-id>          | meter      | Requests/second sent to a given broker                        |
    31   | request-size                                 | histogram  | Distribution of the request size in bytes for all brokers     |
    32   | request-size-for-broker-<broker-id>          | histogram  | Distribution of the request size in bytes for a given broker  |
    33   | request-latency-in-ms                        | histogram  | Distribution of the request latency in ms for all brokers     |
    34   | request-latency-in-ms-for-broker-<broker-id> | histogram  | Distribution of the request latency in ms for a given broker  |
    35   | response-rate                                | meter      | Responses/second received from all brokers                    |
    36   | response-rate-for-broker-<broker-id>         | meter      | Responses/second received from a given broker                 |
    37   | response-size                                | histogram  | Distribution of the response size in bytes for all brokers    |
    38   | response-size-for-broker-<broker-id>         | histogram  | Distribution of the response size in bytes for a given broker |
    39   +----------------------------------------------+------------+---------------------------------------------------------------+
    40  
    41   +-------------------------------------------+------------+--------------------------------------------------------------------------------------+
    42   | Name                                      | Type       | Description                                                                          |
    43   +-------------------------------------------+------------+--------------------------------------------------------------------------------------+
    44   | batch-size                                | histogram  | Distribution of the number of bytes sent per partition per request for all topics    |
    45   | batch-size-for-topic-<topic>              | histogram  | Distribution of the number of bytes sent per partition per request for a given topic |
    46   | record-send-rate                          | meter      | Records/second sent to all topics                                                    |
    47   | record-send-rate-for-topic-<topic>        | meter      | Records/second sent to a given topic                                                 |
    48   | records-per-request                       | histogram  | Distribution of the number of records sent per request for all topics                |
    49   | records-per-request-for-topic-<topic>     | histogram  | Distribution of the number of records sent per request for a given topic             |
    50   | compression-ratio                         | histogram  | Distribution of the compression ratio times 100 of record batches for all topics     |
    51   | compression-ratio-for-topic-<topic>       | histogram  | Distribution of the compression ratio times 100 of record batches for a given topic  |
    52   +-------------------------------------------+------------+--------------------------------------------------------------------------------------+
    53  */
    54  
    55  const (
    56  	IncomingByteRateName  = "incoming-byte-rate-for-broker-"
    57  	OutgoingByteRateName  = "outgoing-byte-rate-for-broker-"
    58  	RequestRateName       = "request-rate-for-broker-"
    59  	RequestSizeName       = "request-size-for-broker-"
    60  	RequestLatencyName    = "request-latency-in-ms-for-broker-"
    61  	ResponseRateName      = "response-rate-for-broker-"
    62  	ResponseSizeName      = "response-size-for-broker-"
    63  	BatchSizeName         = "batch-size-for-topic-"
    64  	RecordSendRateName    = "record-send-rate-for-topic-"
    65  	RecordsPerRequestName = "records-per-request-for-topic-"
    66  	CompressionRatioName  = "compression-ratio-for-topic-"
    67  )
    68  
    69  var (
    70  	incomingByteRate = metrics.GaugeOpts{
    71  		Namespace:    "consensus",
    72  		Subsystem:    "kafka",
    73  		Name:         "incoming_byte_rate",
    74  		Help:         "Bytes/second read off brokers.",
    75  		LabelNames:   []string{"broker_id"},
    76  		StatsdFormat: "%{#fqname}.%{broker_id}",
    77  	}
    78  
    79  	outgoingByteRate = metrics.GaugeOpts{
    80  		Namespace:    "consensus",
    81  		Subsystem:    "kafka",
    82  		Name:         "outgoing_byte_rate",
    83  		Help:         "Bytes/second written to brokers.",
    84  		LabelNames:   []string{"broker_id"},
    85  		StatsdFormat: "%{#fqname}.%{broker_id}",
    86  	}
    87  
    88  	requestRate = metrics.GaugeOpts{
    89  		Namespace:    "consensus",
    90  		Subsystem:    "kafka",
    91  		Name:         "request_rate",
    92  		Help:         "Requests/second sent to brokers.",
    93  		LabelNames:   []string{"broker_id"},
    94  		StatsdFormat: "%{#fqname}.%{broker_id}",
    95  	}
    96  
    97  	requestSize = metrics.GaugeOpts{
    98  		Namespace:    "consensus",
    99  		Subsystem:    "kafka",
   100  		Name:         "request_size",
   101  		Help:         "The mean request size in bytes to brokers.",
   102  		LabelNames:   []string{"broker_id"},
   103  		StatsdFormat: "%{#fqname}.%{broker_id}",
   104  	}
   105  
   106  	requestLatency = metrics.GaugeOpts{
   107  		Namespace:    "consensus",
   108  		Subsystem:    "kafka",
   109  		Name:         "request_latency",
   110  		Help:         "The mean request latency in ms to brokers.",
   111  		LabelNames:   []string{"broker_id"},
   112  		StatsdFormat: "%{#fqname}.%{broker_id}",
   113  	}
   114  
   115  	responseRate = metrics.GaugeOpts{
   116  		Namespace:    "consensus",
   117  		Subsystem:    "kafka",
   118  		Name:         "response_rate",
   119  		Help:         "Requests/second sent to brokers.",
   120  		LabelNames:   []string{"broker_id"},
   121  		StatsdFormat: "%{#fqname}.%{broker_id}",
   122  	}
   123  
   124  	responseSize = metrics.GaugeOpts{
   125  		Namespace:    "consensus",
   126  		Subsystem:    "kafka",
   127  		Name:         "response_size",
   128  		Help:         "The mean response size in bytes from brokers.",
   129  		LabelNames:   []string{"broker_id"},
   130  		StatsdFormat: "%{#fqname}.%{broker_id}",
   131  	}
   132  
   133  	batchSize = metrics.GaugeOpts{
   134  		Namespace:    "consensus",
   135  		Subsystem:    "kafka",
   136  		Name:         "batch_size",
   137  		Help:         "The mean batch size in bytes sent to topics.",
   138  		LabelNames:   []string{"topic"},
   139  		StatsdFormat: "%{#fqname}.%{topic}",
   140  	}
   141  
   142  	recordSendRate = metrics.GaugeOpts{
   143  		Namespace:    "consensus",
   144  		Subsystem:    "kafka",
   145  		Name:         "record_send_rate",
   146  		Help:         "The number of records per second sent to topics.",
   147  		LabelNames:   []string{"topic"},
   148  		StatsdFormat: "%{#fqname}.%{topic}",
   149  	}
   150  
   151  	recordsPerRequest = metrics.GaugeOpts{
   152  		Namespace:    "consensus",
   153  		Subsystem:    "kafka",
   154  		Name:         "records_per_request",
   155  		Help:         "The mean number of records sent per request to topics.",
   156  		LabelNames:   []string{"topic"},
   157  		StatsdFormat: "%{#fqname}.%{topic}",
   158  	}
   159  
   160  	compressionRatio = metrics.GaugeOpts{
   161  		Namespace:    "consensus",
   162  		Subsystem:    "kafka",
   163  		Name:         "compression_ratio",
   164  		Help:         "The mean compression ratio (as percentage) for topics.",
   165  		LabelNames:   []string{"topic"},
   166  		StatsdFormat: "%{#fqname}.%{topic}",
   167  	}
   168  
   169  	lastOffsetPersisted = metrics.GaugeOpts{
   170  		Namespace:    "consensus",
   171  		Subsystem:    "kafka",
   172  		Name:         "last_offset_persisted",
   173  		Help:         "The offset specified in the block metadata of the most recently committed block.",
   174  		LabelNames:   []string{"channel"},
   175  		StatsdFormat: "%{#fqname}.%{channel}",
   176  	}
   177  )
   178  
   179  type Metrics struct {
   180  	// The first set of metrics are all reported by Sarama
   181  	IncomingByteRate  metrics.Gauge
   182  	OutgoingByteRate  metrics.Gauge
   183  	RequestRate       metrics.Gauge
   184  	RequestSize       metrics.Gauge
   185  	RequestLatency    metrics.Gauge
   186  	ResponseRate      metrics.Gauge
   187  	ResponseSize      metrics.Gauge
   188  	BatchSize         metrics.Gauge
   189  	RecordSendRate    metrics.Gauge
   190  	RecordsPerRequest metrics.Gauge
   191  	CompressionRatio  metrics.Gauge
   192  
   193  	GoMetricsRegistry gometrics.Registry
   194  
   195  	// LastPersistedOffset is reported by the Fabric/Kafka integration
   196  	LastOffsetPersisted metrics.Gauge
   197  }
   198  
   199  func NewMetrics(p metrics.Provider, registry gometrics.Registry) *Metrics {
   200  	return &Metrics{
   201  		IncomingByteRate:  p.NewGauge(incomingByteRate),
   202  		OutgoingByteRate:  p.NewGauge(outgoingByteRate),
   203  		RequestRate:       p.NewGauge(requestRate),
   204  		RequestSize:       p.NewGauge(requestSize),
   205  		RequestLatency:    p.NewGauge(requestLatency),
   206  		ResponseRate:      p.NewGauge(responseRate),
   207  		ResponseSize:      p.NewGauge(responseSize),
   208  		BatchSize:         p.NewGauge(batchSize),
   209  		RecordSendRate:    p.NewGauge(recordSendRate),
   210  		RecordsPerRequest: p.NewGauge(recordsPerRequest),
   211  		CompressionRatio:  p.NewGauge(compressionRatio),
   212  
   213  		GoMetricsRegistry: registry,
   214  
   215  		LastOffsetPersisted: p.NewGauge(lastOffsetPersisted),
   216  	}
   217  }
   218  
   219  // PollGoMetrics takes the current metric values from go-metrics and publishes them to
   220  // the gauges exposed through go-kit's metrics.
   221  func (m *Metrics) PollGoMetrics() {
   222  	m.GoMetricsRegistry.Each(func(name string, value interface{}) {
   223  		recordMeter := func(prefix, label string, gauge metrics.Gauge) bool {
   224  			if !strings.HasPrefix(name, prefix) {
   225  				return false
   226  			}
   227  
   228  			meter, ok := value.(gometrics.Meter)
   229  			if !ok {
   230  				logger.Panicf("Expected metric with name %s to be of type Meter but was of type %T", name, value)
   231  			}
   232  
   233  			labelValue := name[len(prefix):]
   234  			gauge.With(label, labelValue).Set(meter.Snapshot().Rate1())
   235  
   236  			return true
   237  		}
   238  
   239  		recordHistogram := func(prefix, label string, gauge metrics.Gauge) bool {
   240  			if !strings.HasPrefix(name, prefix) {
   241  				return false
   242  			}
   243  
   244  			histogram, ok := value.(gometrics.Histogram)
   245  			if !ok {
   246  				logger.Panicf("Expected metric with name %s to be of type Histogram but was of type %T", name, value)
   247  			}
   248  
   249  			labelValue := name[len(prefix):]
   250  			gauge.With(label, labelValue).Set(histogram.Snapshot().Mean())
   251  
   252  			return true
   253  		}
   254  
   255  		switch {
   256  		case recordMeter(IncomingByteRateName, "broker_id", m.IncomingByteRate):
   257  		case recordMeter(OutgoingByteRateName, "broker_id", m.OutgoingByteRate):
   258  		case recordMeter(RequestRateName, "broker_id", m.RequestRate):
   259  		case recordHistogram(RequestSizeName, "broker_id", m.RequestSize):
   260  		case recordHistogram(RequestLatencyName, "broker_id", m.RequestLatency):
   261  		case recordMeter(ResponseRateName, "broker_id", m.ResponseRate):
   262  		case recordHistogram(ResponseSizeName, "broker_id", m.ResponseSize):
   263  		case recordHistogram(BatchSizeName, "topic", m.BatchSize):
   264  		case recordMeter(RecordSendRateName, "topic", m.RecordSendRate):
   265  		case recordHistogram(RecordsPerRequestName, "topic", m.RecordsPerRequest):
   266  		case recordHistogram(CompressionRatioName, "topic", m.CompressionRatio):
   267  		default:
   268  			// Ignore unknown metrics
   269  		}
   270  	})
   271  }
   272  
   273  // PollGoMetricsUntilStop should generally be invoked on a dedicated go routine.  This go routine
   274  // will then invoke PollGoMetrics at the specified frequency until the stopChannel closes.
   275  func (m *Metrics) PollGoMetricsUntilStop(frequency time.Duration, stopChannel <-chan struct{}) {
   276  	timer := time.NewTimer(frequency)
   277  	defer timer.Stop()
   278  	for {
   279  		select {
   280  		case <-timer.C:
   281  			m.PollGoMetrics()
   282  			timer.Reset(frequency)
   283  		case <-stopChannel:
   284  			return
   285  		}
   286  	}
   287  }