Skip to content

Expose xDS updates metrics for library clients #8234

@sevaorlov

Description

@sevaorlov

Hi, how can I get xDS updates metrics?

I am interested in monitoring xDS updates frequency to our service and noticed there was metrics recorder added in this PR #8038.

I don't understand is how I can provide my own metrics recorder implementation and get those metrics.

What I ended up doing is fetching the resolver and wrapping it together with metrics recorder.

base := resolver.Get("xds")
resolver.Register(wrappedResolver{baseResolver: base, context: ctx, recordUpdate: recordUpdate})

type wrappedResolver struct {
	baseResolver resolver.Builder
	recordUpdate metricRecorderFunc
}

func (r wrappedResolver) Build(target resolver.Target, cc resolver.ClientConn,
	opts resolver.BuildOptions) (resolver.Resolver, error) {
	opts.MetricsRecorder = wrappedMetricsRecorder{
		base:         opts.MetricsRecorder,
		recordUpdate: r.recordUpdate,
	}

	return r.baseResolver.Build(target, cc, opts)
}

func (r wrappedResolver) Scheme() string {
	return r.baseResolver.Scheme()
}
type metricRecorderFunc func(ctx context.Context, incr int64, name string)

type wrappedMetricsRecorder struct {
	base stats.MetricsRecorder
	recordUpdate metricRecorderFunc
}

func (w wrappedMetricsRecorder) RecordInt64Count(handle *stats.Int64CountHandle, incr int64, labels ...string) {
	if w.base != nil {
		w.base.RecordInt64Count(handle, incr, labels...)
	}

	w.recordUpdate(incr, handle.Name)
}

func (w wrappedMetricsRecorder) RecordFloat64Count(handle *stats.Float64CountHandle, incr float64, labels ...string) {
	if w.base != nil {
		w.base.RecordFloat64Count(handle, incr, labels...)
	}
}

func (w wrappedMetricsRecorder) RecordInt64Histo(handle *stats.Int64HistoHandle, incr int64, labels ...string) {
	if w.base != nil {
		w.base.RecordInt64Histo(handle, incr, labels...)
	}
}

func (w wrappedMetricsRecorder) RecordFloat64Histo(handle *stats.Float64HistoHandle, incr float64, labels ...string) {
	if w.base != nil {
		w.base.RecordFloat64Histo(handle, incr, labels...)
	}
}

func (w wrappedMetricsRecorder) RecordInt64Gauge(handle *stats.Int64GaugeHandle, incr int64, labels ...string) {
	if w.base != nil {
		w.base.RecordInt64Gauge(handle, incr, labels...)
	}
}

We use GCP Cloud Service Mesh (Traffic Director) if that matters.

Metadata

Metadata

Labels

Area: ObservabilityIncludes Stats, Tracing, Channelz, Healthz, Binlog, Reflection, Admin, GCP ObservabilityType: Question

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions