// eachRecordableValue visits each metric in the registry, calling the supplied // function once for each recordable value represented by that metric. This is // useful to expand certain metric types (such as histograms) into multiple // recordable values. func eachRecordableValue(reg *metric.Registry, fn func(string, float64)) { reg.Each(func(name string, mtr interface{}) { if histogram, ok := mtr.(*metric.Histogram); ok { // TODO(mrtracy): Where should this comment go for better // visibility? // // Proper support of Histograms for time series is difficult and // likely not worth the trouble. Instead, we aggregate a windowed // histogram at fixed quantiles. If the scraping window and the // histogram's eviction duration are similar, this should give // good results; if the two durations are very different, we either // report stale results or report only the more recent data. // // Additionally, we can only aggregate max/min of the quantiles; // roll-ups don't know that and so they will return mathematically // nonsensical values, but that seems acceptable for the time // being. curr, _ := histogram.Windowed() for _, pt := range recordHistogramQuantiles { fn(name+pt.suffix, float64(curr.ValueAtQuantile(pt.quantile))) } } else { val, err := extractValue(mtr) if err != nil { log.Warning(context.TODO(), err) return } fn(name, val) } }) }
// newServer creates and returns a server struct. func newServer( ambient log.AmbientContext, nodeID *base.NodeIDContainer, stopper *stop.Stopper, registry *metric.Registry, ) *server { s := &server{ AmbientContext: ambient, NodeID: nodeID, stopper: stopper, tighten: make(chan struct{}, 1), nodeMetrics: makeMetrics(), serverMetrics: makeMetrics(), } s.mu.is = newInfoStore(s.AmbientContext, nodeID, util.UnresolvedAddr{}, stopper) s.mu.incoming = makeNodeSet(minPeers, metric.NewGauge(MetaConnectionsIncomingGauge)) s.mu.nodeMap = make(map[util.UnresolvedAddr]serverInfo) s.mu.ready = make(chan struct{}) registry.AddMetric(s.mu.incoming.gauge) registry.AddMetricStruct(s.nodeMetrics) return s }
func makeNodeMetrics(reg *metric.Registry, sampleInterval time.Duration) nodeMetrics { nm := nodeMetrics{ Latency: metric.NewLatency(metaExecLatency, sampleInterval), Success: metric.NewCounter(metaExecSuccess), Err: metric.NewCounter(metaExecError), } reg.AddMetricStruct(nm) return nm }
// New creates an instance of a gossip node. // The higher level manages the NodeIDContainer instance (which can be shared by // various server components). The ambient context is expected to already // contain the node ID. func New( ambient log.AmbientContext, nodeID *base.NodeIDContainer, rpcContext *rpc.Context, grpcServer *grpc.Server, resolvers []resolver.Resolver, stopper *stop.Stopper, registry *metric.Registry, ) *Gossip { ambient.SetEventLog("gossip", "gossip") g := &Gossip{ server: newServer(ambient, nodeID, stopper, registry), Connected: make(chan struct{}), rpcContext: rpcContext, outgoing: makeNodeSet(minPeers, metric.NewGauge(MetaConnectionsOutgoingGauge)), bootstrapping: map[string]struct{}{}, disconnected: make(chan *client, 10), stalledCh: make(chan struct{}, 1), stallInterval: defaultStallInterval, bootstrapInterval: defaultBootstrapInterval, cullInterval: defaultCullInterval, nodeDescs: map[roachpb.NodeID]*roachpb.NodeDescriptor{}, resolverAddrs: map[util.UnresolvedAddr]resolver.Resolver{}, bootstrapAddrs: map[util.UnresolvedAddr]roachpb.NodeID{}, } stopper.AddCloser(stop.CloserFn(g.server.AmbientContext.FinishEventLog)) registry.AddMetric(g.outgoing.gauge) g.clientsMu.breakers = map[string]*circuit.Breaker{} resolverAddrs := make([]string, len(resolvers)) for i, resolver := range resolvers { resolverAddrs[i] = resolver.Addr() } ctx := g.AnnotateCtx(context.Background()) if log.V(1) { log.Infof(ctx, "initial resolvers: %v", resolverAddrs) } g.SetResolvers(resolvers) g.mu.Lock() // Add ourselves as a SystemConfig watcher. g.mu.is.registerCallback(KeySystemConfig, g.updateSystemConfig) // Add ourselves as a node descriptor watcher. g.mu.is.registerCallback(MakePrefixPattern(KeyNodeIDPrefix), g.updateNodeAddress) g.mu.Unlock() RegisterGossipServer(grpcServer, g.server) return g }