本文主要研究一下dubbo-go的PrometheusReporterapp
dubbo-go-v1.4.2/metrics/prometheus/reporter.goide
const ( reporterName = "prometheus" serviceKey = constant.SERVICE_KEY groupKey = constant.GROUP_KEY versionKey = constant.VERSION_KEY methodKey = constant.METHOD_KEY timeoutKey = constant.TIMEOUT_KEY providerKey = "provider" consumerKey = "consumer" // to identify the metric's type histogramSuffix = "_histogram" // to identify the metric's type summarySuffix = "_summary" ) var ( labelNames = []string{serviceKey, groupKey, versionKey, methodKey, timeoutKey} namespace = config.GetApplicationConfig().Name reporterInstance *PrometheusReporter reporterInitOnce sync.Once ) // should initialize after loading configuration func init() { extension.SetMetricReporter(reporterName, newPrometheusReporter) } // PrometheusReporter // it will collect the data for Prometheus // if you want to use this, you should initialize your prometheus. // https://prometheus.io/docs/guides/go-application/ type PrometheusReporter struct { // report the consumer-side's summary data consumerSummaryVec *prometheus.SummaryVec // report the provider-side's summary data providerSummaryVec *prometheus.SummaryVec // report the provider-side's histogram data providerHistogramVec *prometheus.HistogramVec // report the consumer-side's histogram data consumerHistogramVec *prometheus.HistogramVec }
dubbo-go-v1.4.2/metrics/prometheus/reporter.goui
// newPrometheusReporter create new prometheusReporter // it will register the metrics into prometheus func newPrometheusReporter() metrics.Reporter { if reporterInstance == nil { reporterInitOnce.Do(func() { reporterInstance = &PrometheusReporter{ consumerSummaryVec: newSummaryVec(consumerKey), providerSummaryVec: newSummaryVec(providerKey), consumerHistogramVec: newHistogramVec(consumerKey), providerHistogramVec: newHistogramVec(providerKey), } prometheus.MustRegister(reporterInstance.consumerSummaryVec, reporterInstance.providerSummaryVec, reporterInstance.consumerHistogramVec, reporterInstance.providerHistogramVec) }) } return reporterInstance }
dubbo-go-v1.4.2/metrics/prometheus/reporter.gothis
// newSummaryVec create SummaryVec, the Namespace is dubbo // the objectives is from my experience. func newSummaryVec(side string) *prometheus.SummaryVec { return prometheus.NewSummaryVec( prometheus.SummaryOpts{ Namespace: namespace, Help: "This is the dubbo's summary metrics", Subsystem: side, Name: serviceKey + summarySuffix, Objectives: map[float64]float64{ 0.5: 0.01, 0.75: 0.01, 0.90: 0.005, 0.98: 0.002, 0.99: 0.001, 0.999: 0.0001, }, }, labelNames, ) }
dubbo-go-v1.4.2/metrics/prometheus/reporter.gourl
func newHistogramVec(side string) *prometheus.HistogramVec { mc := config.GetMetricConfig() return prometheus.NewHistogramVec( prometheus.HistogramOpts{ Namespace: namespace, Subsystem: side, Name: serviceKey + histogramSuffix, Help: "This is the dubbo's histogram metrics", Buckets: mc.GetHistogramBucket(), }, labelNames) }
dubbo-go-v1.4.2/metrics/prometheus/reporter.gospa
// Report report the duration to Prometheus // the role in url must be consumer or provider // or it will be ignored func (reporter *PrometheusReporter) Report(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) { url := invoker.GetUrl() var sumVec *prometheus.SummaryVec var hisVec *prometheus.HistogramVec if isProvider(url) { sumVec = reporter.providerSummaryVec hisVec = reporter.providerHistogramVec } else if isConsumer(url) { sumVec = reporter.consumerSummaryVec hisVec = reporter.consumerHistogramVec } else { logger.Warnf("The url is not the consumer's or provider's, "+ "so the invocation will be ignored. url: %s", url.String()) return } labels := prometheus.Labels{ serviceKey: url.Service(), groupKey: url.GetParam(groupKey, ""), versionKey: url.GetParam(versionKey, ""), methodKey: invocation.MethodName(), timeoutKey: url.GetParam(timeoutKey, ""), } costMs := float64(cost.Nanoseconds() / constant.MsToNanoRate) sumVec.With(labels).Observe(costMs) hisVec.With(labels).Observe(costMs) } // whether this url represents the application received the request as server func isProvider(url common.URL) bool { role := url.GetParam(constant.ROLE_KEY, "") return strings.EqualFold(role, strconv.Itoa(common.PROVIDER)) } // whether this url represents the application sent then request as client func isConsumer(url common.URL) bool { role := url.GetParam(constant.ROLE_KEY, "") return strings.EqualFold(role, strconv.Itoa(common.CONSUMER)) }
PrometheusReporter定義了consumerSummaryVec、providerSummaryVec、providerHistogramVec、consumerHistogramVec;Report方法根據url來判斷是provider仍是consumer,若爲provider則獲取reporter.providerSummaryVec、reporter.providerHistogramVec;若爲consumer則獲取reporter.consumerSummaryVec、reporter.consumerHistogramVec;以後設置labels,而後執行sumVec.With(labels).Observe(costMs)及hisVec.With(labels).Observe(costMs)code